diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp
index 0e90d271fbfc9f7f94443ca38f0d815b004b3ffc..f21b211734337ca77178f6a3fc366303dac23639 100644
--- a/aconversions2/src/ConversionHandler.cpp
+++ b/aconversions2/src/ConversionHandler.cpp
@@ -25,8 +25,8 @@
 #include "regexp/convert/ToGrammarRightRGGlushkov.h"
 #include "regexp/convert/ToGrammarRightRGDerivation.h"
 
+#include "rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.h"
 #include "rte/convert/ToPostfixPushdownAutomatonGlushkov.h"
-#include "rte/convert/ToPostfixPushdownAutomatonGlushkovV3.h"
 
 #include <factory/XmlDataFactory.hpp>
 #include <exception/CommonException.h>
@@ -342,8 +342,8 @@ void ConversionHandler::convertRTEtoPDA ( void ) {
 	measurements::start ( "Algorithm", measurements::Type::MAIN );
 
 	switch ( m_algorithm ) {
-	case GLUSHKOV_RTE: {
-		automaton::NPDA < > automaton = rte::convert::ToPostfixPushdownAutomatonGlushkov::convert ( rte );
+	case GLUSHKOV_RTE_NAIVE: {
+		automaton::NPDA < > automaton = rte::convert::ToPostfixPushdownAutomatonGlushkovNaive::convert ( rte );
 
 		measurements::end ( );
 		measurements::start ( "Output write", measurements::Type::AUXILIARY );
@@ -351,8 +351,8 @@ void ConversionHandler::convertRTEtoPDA ( void ) {
 		alib::XmlDataFactory::toStdout ( automaton );
 		break;
 	}
-	case GLUSHKOV_RTE_V3: {
-		automaton::Automaton automaton = rte::convert::ToPostfixPushdownAutomatonGlushkovV3::convert ( rte );
+	case GLUSHKOV_RTE: {
+		automaton::Automaton automaton = rte::convert::ToPostfixPushdownAutomatonGlushkov::convert ( rte );
 
 		measurements::end ( );
 		measurements::start ( "Output write", measurements::Type::AUXILIARY );
@@ -444,9 +444,9 @@ ConversionHandler::TAlgorithm ConversionHandler::parseAlgorithmFromString ( cons
 
 	if ( algorithm == "bottomup" ) return BOTTOM_UP;
 
-	if ( algorithm == "glushkovrte" ) return GLUSHKOV_RTE;
+	if ( algorithm == "glushkovrtenaive" ) return GLUSHKOV_RTE_NAIVE;
 
-	if ( algorithm == "glushkovrtev3" ) return GLUSHKOV_RTE_V3;
+	if ( algorithm == "glushkovrte" ) return GLUSHKOV_RTE;
 
 	if ( ( algorithm == "" ) || ( algorithm == "default" ) ) return DEFAULT;
 
diff --git a/aconversions2/src/ConversionHandler.h b/aconversions2/src/ConversionHandler.h
index 1961101188bd0c66f366d9c1e1564871d3c76988..e9c61e97ab93676ccfe307c501e197cb291e36f9 100644
--- a/aconversions2/src/ConversionHandler.h
+++ b/aconversions2/src/ConversionHandler.h
@@ -30,7 +30,7 @@ public:
 		 /* CFG to PDA */
 		BOTTOM_UP, TOP_DOWN,
 		 /* RTE to PDA */
-		GLUSHKOV_RTE, GLUSHKOV_RTE_V3,
+		GLUSHKOV_RTE_NAIVE, GLUSHKOV_RTE,
 	};
 
 	enum TFormalism {
diff --git a/aconversions2/src/aconversion.cpp b/aconversions2/src/aconversion.cpp
index 5fc891a875eed141cc3c30e6098789ff0742c5ec..dfaecc8e24f5c79fb279877239594d28d16ed5dc 100644
--- a/aconversions2/src/aconversion.cpp
+++ b/aconversions2/src/aconversion.cpp
@@ -30,7 +30,7 @@ int main ( int argc, char * argv[] ) {
 		cmd.add ( target );
 
 		std::vector < std::string > algorithms {
-			"algebraic", "elimination", "brzozowski", "glushkov", "thompson", "incoming", "outgoing", "bottomup", "topdown", "default", "glushkovrte", "glushkovrtev3"
+			"algebraic", "elimination", "brzozowski", "glushkov", "thompson", "incoming", "outgoing", "bottomup", "topdown", "default", "glushkovrtenaive", "glushkovrte"
 		};
 		TCLAP::ValuesConstraint < std::string > allowedAlgorithms ( algorithms );
 		TCLAP::ValueArg < std::string > algorithm ( "a", "algorithm", "Specifies algorithm to use", false, "default", & allowedAlgorithms );
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.cpp b/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.cpp
index 4d10836452b4b2a6a46ae4c03fd222e20539876c..638b45232ca5511184e1ceaced24d240b960c6c2 100644
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.cpp
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.cpp
@@ -6,7 +6,7 @@
  */
 
 #include "ToPostfixPushdownAutomaton.h"
-#include "ToPostfixPushdownAutomatonGlushkov.h"
+#include "ToPostfixPushdownAutomatonGlushkovNaive.h"
 #include <exception/CommonException.h>
 #include <registration/AlgoRegistration.hpp>
 
@@ -19,7 +19,7 @@ automaton::Automaton ToPostfixPushdownAutomaton::convert ( const rte::RTE & rte
 }
 
 automaton::Automaton ToPostfixPushdownAutomaton::convert ( const rte::FormalRTE < > & rte ) {
-	return automaton::Automaton ( ToPostfixPushdownAutomatonGlushkov::convert ( rte ) );
+	return automaton::Automaton ( ToPostfixPushdownAutomatonGlushkovNaive::convert ( rte ) );
 }
 
 auto ToAutomatonFormalRegExp = registration::OverloadRegister < ToPostfixPushdownAutomaton, automaton::Automaton, rte::FormalRTE < > > ( ToPostfixPushdownAutomaton::convert );
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.h b/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.h
index b0572f93e28425953c6fb71414e47dd474227221..f618d427aad6e104ed083ce8c5d0b7730b811498 100644
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.h
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomaton.h
@@ -13,8 +13,6 @@
 #include <rte/RTE.h>
 #include <rte/formal/FormalRTE.h>
 
-// #include <rte/unbounded/UnboundedRegExp.h>
-
 #include <automaton/Automaton.h>
 
 namespace rte {
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.cpp b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.cpp
index c32399341808fc7225117620564bd5f4a8381f57..bbed287580e01027bcc5551959ad567a252bf807 100644
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.cpp
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.cpp
@@ -1,43 +1,42 @@
 /*
- * ToPostfixPushdownAutomatonGlushkov.h
+ * ToPostfixPushdownAutomatonGlushkov.cpp
  *
- *  Created on: 11. 4. 2016
+ *  Created on: 26. 7. 2017
  *	  Author: Tomas Pecka
  */
 
 #include "ToPostfixPushdownAutomatonGlushkov.h"
 
-#include "alphabet/BottomOfTheStackSymbol.h"
-#include "alphabet/EndSymbol.h"
-
 #include <automaton/Automaton.h>
+#include <alphabet/BottomOfTheStackSymbol.h>
+#include <alphabet/EndSymbol.h>
 
-#include "global/GlobalData.h"
+#include <global/GlobalData.h>
+#include <registration/AlgoRegistration.hpp>
 
 #include "../glushkov/GlushkovFollow.h"
 #include "../glushkov/GlushkovIndexate.h"
 #include "../glushkov/GlushkovFirst.h"
-#include <registration/AlgoRegistration.hpp>
+#include "../glushkov/GlushkovSubstitutionMap.h"
 
 namespace rte {
 
 namespace convert {
 
-automaton::NPDA < > ToPostfixPushdownAutomatonGlushkov::convert ( const rte::RTE & rte ) {
+automaton::Automaton ToPostfixPushdownAutomatonGlushkov::convert ( const rte::RTE & rte ) {
 	return dispatch ( rte.getData ( ) );
 }
 
-std::vector < DefaultSymbolType > phi ( const std::vector < std::ranked_symbol < > > & follow ) {
-	return std::transform < DefaultSymbolType > ( follow, []( const std::ranked_symbol < > & symbol ) { return DefaultSymbolType ( alphabet::RankedSymbol < > ( symbol ) ); } );
-}
-
-bool isSubstSymbolPresent ( const std::set < std::ranked_symbol < > > & container, const std::set < std::ranked_symbol < > > & substAlphabet ) {
+template < class SymbolType, class RankType >
+bool ToPostfixPushdownAutomatonGlushkov::isSubstSymbolPresent ( const std::set < std::ranked_symbol < SymbolType, RankType > > & container, const TAlphabet < SymbolType, RankType > & substAlphabet ) {
 	std::vector < std::ranked_symbol < > > intersection;
 	std::set_intersection ( container.begin ( ), container.end ( ), substAlphabet.begin ( ), substAlphabet.end ( ), std::back_inserter ( intersection ) );
 	return intersection.size ( ) > 0;
 }
 
-automaton::NPDA < > ToPostfixPushdownAutomatonGlushkov::convert ( const rte::FormalRTE < > & rte ) {
+template < class SymbolType, class RankType >
+automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType >
+ToPostfixPushdownAutomatonGlushkov::convert ( const rte::FormalRTE < > & rte ) {
 
 	 // step 1; index RTE
 	rte::FormalRTE < > indexedRTE = rte::GlushkovIndexate::index ( rte );
@@ -47,26 +46,31 @@ automaton::NPDA < > ToPostfixPushdownAutomatonGlushkov::convert ( const rte::For
 	const std::set < std::ranked_symbol < > > firstSet = rte::GlushkovFirst::first ( indexedRTE );
 
 	 // - follow set for every element of (non-indexed) RTE alphabet element
-	std::map < std::ranked_symbol < >, std::set < std::vector < std::ranked_symbol < > > > > followSet;
+	const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > substMapTree = GlushkovSubstitutionMap::substMap ( indexedRTE );
+	std::map < std::ranked_symbol < >, std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > > followSet;
 
 	for ( const std::ranked_symbol < > & symbol : indexedRTE.getAlphabet ( ) )
-		followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollow::follow ( indexedRTE, symbol ) ) );
+		followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollow::follow ( indexedRTE, symbol, substMapTree ) ) );
 
-	 /* check for exceptions -> there must be NO substitution symbol in first or follow sets */
+	/* check for exceptions -> there must be NO substitution symbol in first set */
 	if ( isSubstSymbolPresent ( firstSet, rte.getSubstitutionAlphabet ( ) ) )
 		throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in the first set" );
+	/* check end */
 
-	for ( const auto & kv : followSet )
-		for ( const auto & followTuple : kv.second )
-			if ( isSubstSymbolPresent ( std::set < std::ranked_symbol < > > ( followTuple.begin ( ), followTuple.end ( ) ), rte.getSubstitutionAlphabet ( ) ) )
-				throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in a follow set" );
-
+	/* check for exceptions -> there must be NO substitution symbol in follow sets */
+	for ( const std::pair < const std::ranked_symbol < SymbolType, RankType >, std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > > & kv : followSet )
+		for ( const GlushkovFollow::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) // TFollowTuple = vector < set < ranked_symbol > >
+			for ( const std::set < std::ranked_symbol < SymbolType, RankType > > & followTupleElem : followTuple )
+				if ( isSubstSymbolPresent ( followTupleElem, rte.getSubstitutionAlphabet ( ) ) )
+					throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in a follow set" );
 	/* check end */
 
 	 // step 3; create PDA (w/o transitions yet) and initialize input alphabet = (non-indexed) RTE alphabet and END symbol
 	DefaultStateType q = DefaultStateType ( 'q' );
 	DefaultStateType f = DefaultStateType ( 'f' );
-	automaton::NPDA < > automaton ( q, alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ) );
+
+	auto BotS = std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >::template from < alphabet::BottomOfTheStackSymbol > ( );
+	automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType > automaton ( q, BotS );
 
 	automaton.addState ( f );
 	automaton.addFinalState ( f );
@@ -76,11 +80,22 @@ automaton::NPDA < > ToPostfixPushdownAutomatonGlushkov::convert ( const rte::For
 
 	automaton.addInputSymbol ( alphabet::EndSymbol::instance < DefaultSymbolType > ( ) );
 
-	 // step 4; create pushdown store alphabet; it consists of elements of indexed RTE alphabet and BotS symbol
+	// step 4; create pushdown store alphabet;
+
+	// simple
 	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) )
-		automaton.addPushdownStoreSymbol ( DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) );
+		automaton.addPushdownStoreSymbol ( std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > ( { symb } ) );
 
-	 /* DEBUG */
+	// complex
+	for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) {
+		if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) ) { 
+			for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) {
+				automaton.addPushdownStoreSymbol ( kv2.second );
+			}
+		}
+	}
+
+	/* DEBUG */
 	if ( common::GlobalData::verbose ) {
 		std::cerr << "RTE:" << std::endl;
 
@@ -96,47 +111,122 @@ automaton::NPDA < > ToPostfixPushdownAutomatonGlushkov::convert ( const rte::For
 
 		std::cerr << std::endl;
 
-		for ( const auto & kv : followSet ) {
+		// std::map < std::ranked_symbol < >, std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > > followSet;
+		for ( const std::pair < const std::ranked_symbol < >, std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > >& kv : followSet ) {
 			std::cerr << "Follow(RTE, " << kv.first << "):" << std::endl;
 
 			if ( kv.second.empty ( ) )
 				std::cerr << "\t" << "{}" << std::endl;
 
-			for ( const auto & follow : kv.second ) {
-				for ( const auto & symbol : follow )
-					std::cerr << "\t" << symbol << std::endl;
+			for ( const GlushkovFollow::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) { // TFollowTuple = vector < set < ranked_symbol > >
+				std::cerr << " \t - FollowTuple:" << std::endl;
+				for ( const std::set < std::ranked_symbol < > > & child : followTuple )
+					std::cerr << "\t\t - " << child << std::endl;
 
 				std::cerr << std::endl;
 			}
 
 			std::cerr << std::endl;
 		}
+
+		std::cerr << "---------------------------------------------------------" << std::endl;
+		std::cerr << "PDA:" << std::endl;
+		std::cerr << "pds symbols" << std::endl;
+
+		for ( const auto & symb : automaton.getPushdownStoreAlphabet ( ) )
+			std::cerr << "\t" << symb << std::endl;
+		std::cerr << std::endl;
 	}
 	/* DEBUG END */
 
+
+	/* TRANSITIONS */
+	// Pattern 3 and 2
 	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) {
-		if ( symb.getRank ( ) == primitive::Unsigned ( 0 ) )
-			automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, { DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) } );
-		else
-			for ( const std::vector < std::ranked_symbol < > > & follow : followSet[symb] ) {
-				std::vector < DefaultSymbolType > fstring = phi ( follow );
-				std::reverse ( fstring.begin ( ), fstring.end ( ) );
-				automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), fstring, q, { DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) } );
+		if ( symb.getRank ( ) == primitive::Unsigned ( 0 ) ) {
+			std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > push;
+			push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
+
+			if ( common::GlobalData::verbose ) {
+				std::cerr << "Transition 3: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
+					"\t" << "[]" << std::endl <<
+					"\t ->" << std::endl <<
+					"\t" << push << std::endl << std::endl;
 			}
+			automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, push );
+		} else {
+			for ( const GlushkovFollow::TFollowTuple < SymbolType, RankType > & followTuple : followSet [ symb ] ) { //tuple = vector < set < symb > >
+				std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push;
+
+				/*
+				for ( const auto & e : symbFollowTuple )
+				   pop.push_back ( e );
+				std::reverse ( pop.begin ( ), pop.end ( ) ); // <------------ WTF. CRASHES HERE // FIXME
+				*/
+				for ( const auto & e : followTuple )
+					pop.insert ( pop.begin ( ), e );
+
+				push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
+
+				if ( common::GlobalData::verbose ) {
+					std::cerr << "Transition 2: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
+						"\t" << pop << std::endl <<
+						"\t ->" << std::endl <<
+						"\t" << push << std::endl << std::endl;
+				}
+				automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push );
+			}
+		}
+	}
+
+	// Pattern 1
+	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) {
+		for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) {
+			if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) == nullptr ) // not a SubstSymbol node
+				continue;
 
+			for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) {
+				if ( kv2.second.count ( symb ) == 0 ) 
+					continue;
+
+				for ( const GlushkovFollow::TFollowTuple < SymbolType, RankType > & symbFollowTuple : followSet [ symb ] ) {
+					std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push;
+
+					if ( ( size_t ) symb.getRank ( ) > 0 ) {
+						for ( const auto & e : symbFollowTuple )
+							pop.insert ( pop.begin ( ), e );
+					}
+
+					push.push_back( kv2.second );
+
+					if ( common::GlobalData::verbose ) {
+						std::cerr << "Transition 1" << ( pop.empty() ? "a" : "b" ) <<  ": " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
+							"\t" << pop << std::endl <<
+							"\t ->" << std::endl <<
+							"\t" << push << std::endl << std::endl;
+					}
+
+					automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push );
+				}
+			}
+		}
 	}
 
+	// Final
 	for ( const std::ranked_symbol < > & symb : firstSet ) {
-		std::vector < DefaultSymbolType > pop;
-		pop.push_back ( DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) );
-		pop.push_back ( alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ) );
+		std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop;
+		pop.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
+		pop.push_back ( BotS );
 		automaton.addTransition ( q, alphabet::EndSymbol::instance < DefaultSymbolType > ( ), pop, f, { } );
 	}
+	/* TRANSITIONS END */
 
 	return automaton;
 }
 
-auto ToAutomatonGlushkovFormalRegExp = registration::OverloadRegister < ToPostfixPushdownAutomatonGlushkov, automaton::NPDA < >, rte::FormalRTE < > > ( ToPostfixPushdownAutomatonGlushkov::convert );
+auto ToPostfixPushdownAutomatonGlushkovFormalRTE = registration::OverloadRegister < ToPostfixPushdownAutomatonGlushkov,
+			automaton::NPDA < DefaultSymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < alib::Object, primitive::Unsigned > > >, DefaultStateType >,
+			rte::FormalRTE < > > ( ToPostfixPushdownAutomatonGlushkov::convert );
 
 } /* namespace convert */
 
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.h b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.h
index d5ef30cf787f17d3efc248aeb8fa4c5f30dcdf4f..c4181477827bbff3d27786ed7e29fcf70b9085e4 100644
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.h
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkov.h
@@ -1,7 +1,7 @@
 /*
  * ToPostfixPushdownAutomatonGlushkov.h
  *
- *  Created on: 11. 4. 2016
+ *  Created on: 26. 7. 2017
  *	  Author: Tomas Pecka
  */
 
@@ -11,12 +11,13 @@
 #include <core/multipleDispatch.hpp>
 #include <map>
 
-#include <automaton/FSM/NFA.h>
 #include <automaton/PDA/NPDA.h>
+
 #include <rte/RTE.h>
 #include <rte/formal/FormalRTE.h>
 
-// #include <rte/unbounded/UnboundedRegExp.h>
+#include <container/ObjectsVariant.h>
+#include <container/ObjectsSet.h>
 
 namespace rte {
 
@@ -26,19 +27,31 @@ namespace convert {
  * Converts regular tree expression to real-time height-deterministic pda
  * Source: Master Thesis, Pecka Tomas, CTU FIT, 2016, chapter 4.2
  */
-class ToPostfixPushdownAutomatonGlushkov : public std::SingleDispatch < ToPostfixPushdownAutomatonGlushkov, automaton::NPDA < >, const rte::RTEBase & > {
+class ToPostfixPushdownAutomatonGlushkov : public std::SingleDispatch < ToPostfixPushdownAutomatonGlushkov, automaton::Automaton, const rte::RTEBase & > {
+private:
+	// --------------------------------------------------------------------
+
+	template < class SymbolType, class RankType >
+	using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >;
+
+	// --------------------------------------------------------------------
+
+	template < class SymbolType, class RankType >
+	static bool isSubstSymbolPresent ( const std::set < std::ranked_symbol < SymbolType, RankType > > & container, const TAlphabet < SymbolType, RankType > & substAlphabet );
 public:
 	/**
 	 * Performs conversion.
 	 * @param re Original regular tree expression.
 	 * @return rhNPDA equivalent to original regular expression.
 	 */
-	static automaton::NPDA < > convert ( const rte::RTE & rte );
-	static automaton::NPDA < > convert ( const rte::FormalRTE < > & rte );
+	static automaton::Automaton convert ( const rte::RTE & rte );
+
+	template < class SymbolType, class RankType >
+	static automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType > convert ( const rte::FormalRTE < > & rte );
 };
 
 } /* namespace convert */
 
 } /* namespace rte */
 
-#endif /* TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_H_ */
+#endif /* TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_V3_H_ */
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.cpp b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..386f93d39efc2496f0a349b3b6495f73e923587c
--- /dev/null
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.cpp
@@ -0,0 +1,143 @@
+/*
+ * ToPostfixPushdownAutomatonGlushkovNaive.h
+ *
+ *  Created on: 11. 4. 2016
+ *	  Author: Tomas Pecka
+ */
+
+#include "ToPostfixPushdownAutomatonGlushkovNaive.h"
+
+#include "alphabet/BottomOfTheStackSymbol.h"
+#include "alphabet/EndSymbol.h"
+
+#include <automaton/Automaton.h>
+
+#include "global/GlobalData.h"
+
+#include "../glushkov/GlushkovFollowNaive.h"
+#include "../glushkov/GlushkovIndexate.h"
+#include "../glushkov/GlushkovFirst.h"
+#include <registration/AlgoRegistration.hpp>
+
+namespace rte {
+
+namespace convert {
+
+automaton::NPDA < > ToPostfixPushdownAutomatonGlushkovNaive::convert ( const rte::RTE & rte ) {
+	return dispatch ( rte.getData ( ) );
+}
+
+std::vector < DefaultSymbolType > phi ( const std::vector < std::ranked_symbol < > > & follow ) {
+	return std::transform < DefaultSymbolType > ( follow, []( const std::ranked_symbol < > & symbol ) { return DefaultSymbolType ( alphabet::RankedSymbol < > ( symbol ) ); } );
+}
+
+bool isSubstSymbolPresent ( const std::set < std::ranked_symbol < > > & container, const std::set < std::ranked_symbol < > > & substAlphabet ) {
+	std::vector < std::ranked_symbol < > > intersection;
+	std::set_intersection ( container.begin ( ), container.end ( ), substAlphabet.begin ( ), substAlphabet.end ( ), std::back_inserter ( intersection ) );
+	return intersection.size ( ) > 0;
+}
+
+automaton::NPDA < > ToPostfixPushdownAutomatonGlushkovNaive::convert ( const rte::FormalRTE < > & rte ) {
+
+	 // step 1; index RTE
+	rte::FormalRTE < > indexedRTE = rte::GlushkovIndexate::index ( rte );
+
+	 // step 2; compute:
+	 // - first set
+	const std::set < std::ranked_symbol < > > firstSet = rte::GlushkovFirst::first ( indexedRTE );
+
+	 // - follow set for every element of (non-indexed) RTE alphabet element
+	std::map < std::ranked_symbol < >, std::set < std::vector < std::ranked_symbol < > > > > followSet;
+
+	for ( const std::ranked_symbol < > & symbol : indexedRTE.getAlphabet ( ) )
+		followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollowNaive::follow ( indexedRTE, symbol ) ) );
+
+	 /* check for exceptions -> there must be NO substitution symbol in first or follow sets */
+	if ( isSubstSymbolPresent ( firstSet, rte.getSubstitutionAlphabet ( ) ) )
+		throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in the first set" );
+
+	for ( const auto & kv : followSet )
+		for ( const auto & followTuple : kv.second )
+			if ( isSubstSymbolPresent ( std::set < std::ranked_symbol < > > ( followTuple.begin ( ), followTuple.end ( ) ), rte.getSubstitutionAlphabet ( ) ) )
+				throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in a follow set" );
+
+	/* check end */
+
+	 // step 3; create PDA (w/o transitions yet) and initialize input alphabet = (non-indexed) RTE alphabet and END symbol
+	DefaultStateType q = DefaultStateType ( 'q' );
+	DefaultStateType f = DefaultStateType ( 'f' );
+	automaton::NPDA < > automaton ( q, alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ) );
+
+	automaton.addState ( f );
+	automaton.addFinalState ( f );
+
+	for ( const std::ranked_symbol < > & symbol : rte.getAlphabet ( ) )
+		automaton.addInputSymbol ( symbol.getSymbol ( ) );
+
+	automaton.addInputSymbol ( alphabet::EndSymbol::instance < DefaultSymbolType > ( ) );
+
+	 // step 4; create pushdown store alphabet; it consists of elements of indexed RTE alphabet and BotS symbol
+	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) )
+		automaton.addPushdownStoreSymbol ( DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) );
+
+	 /* DEBUG */
+	if ( common::GlobalData::verbose ) {
+		std::cerr << "RTE:" << std::endl;
+
+		for ( const auto & symbol : indexedRTE.getAlphabet ( ) )
+			std::cerr << "\t" << symbol << std::endl;
+
+		std::cerr << std::endl;
+
+		std::cerr << "First(RTE):" << std::endl;
+
+		for ( const auto & symbol : firstSet )
+			std::cerr << "\t" << symbol << std::endl;
+
+		std::cerr << std::endl;
+
+		for ( const auto & kv : followSet ) {
+			std::cerr << "Follow(RTE, " << kv.first << "):" << std::endl;
+
+			if ( kv.second.empty ( ) )
+				std::cerr << "\t" << "{}" << std::endl;
+
+			for ( const auto & follow : kv.second ) {
+				for ( const auto & symbol : follow )
+					std::cerr << "\t" << symbol << std::endl;
+
+				std::cerr << std::endl;
+			}
+
+			std::cerr << std::endl;
+		}
+	}
+	/* DEBUG END */
+
+	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) {
+		if ( symb.getRank ( ) == primitive::Unsigned ( 0 ) )
+			automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, { DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) } );
+		else
+			for ( const std::vector < std::ranked_symbol < > > & follow : followSet[symb] ) {
+				std::vector < DefaultSymbolType > fstring = phi ( follow );
+				std::reverse ( fstring.begin ( ), fstring.end ( ) );
+				automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), fstring, q, { DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) } );
+			}
+
+	}
+
+	for ( const std::ranked_symbol < > & symb : firstSet ) {
+		std::vector < DefaultSymbolType > pop;
+		pop.push_back ( DefaultSymbolType ( alphabet::RankedSymbol < > ( symb ) ) );
+		pop.push_back ( alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ) );
+		automaton.addTransition ( q, alphabet::EndSymbol::instance < DefaultSymbolType > ( ), pop, f, { } );
+	}
+
+	return automaton;
+}
+
+auto ToPostfixPushdownAutomatonGlushkovNaiveFormalRTE = registration::OverloadRegister < ToPostfixPushdownAutomatonGlushkovNaive, automaton::NPDA < >, rte::FormalRTE < > > ( ToPostfixPushdownAutomatonGlushkovNaive::convert );
+
+} /* namespace convert */
+
+} /* namespace rte */
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.h b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.h
new file mode 100644
index 0000000000000000000000000000000000000000..a673c3cd6e143ed8b2018d2f14964a4ef6c23530
--- /dev/null
+++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovNaive.h
@@ -0,0 +1,44 @@
+/*
+ * ToPostfixPushdownAutomatonGlushkovNaive.h
+ *
+ *  Created on: 11. 4. 2016
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_NAIVE_H_
+#define TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_NAIVE_H_
+
+#include <core/multipleDispatch.hpp>
+#include <map>
+
+#include <automaton/FSM/NFA.h>
+#include <automaton/PDA/NPDA.h>
+#include <rte/RTE.h>
+#include <rte/formal/FormalRTE.h>
+
+// #include <rte/unbounded/UnboundedRegExp.h>
+
+namespace rte {
+
+namespace convert {
+
+/**
+ * Converts regular tree expression to real-time height-deterministic pda
+ * Source: Master Thesis, Pecka Tomas, CTU FIT, 2016, chapter 4.2
+ */
+class ToPostfixPushdownAutomatonGlushkovNaive : public std::SingleDispatch < ToPostfixPushdownAutomatonGlushkovNaive, automaton::NPDA < >, const rte::RTEBase & > {
+public:
+	/**
+	 * Performs conversion.
+	 * @param re Original regular tree expression.
+	 * @return rhNPDA equivalent to original regular expression.
+	 */
+	static automaton::NPDA < > convert ( const rte::RTE & rte );
+	static automaton::NPDA < > convert ( const rte::FormalRTE < > & rte );
+};
+
+} /* namespace convert */
+
+} /* namespace rte */
+
+#endif /* TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_NAIVE_H_ */
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp
deleted file mode 100644
index b3cec97de896f0344ba4f7200cd3b28ec9935e5a..0000000000000000000000000000000000000000
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * ToPostfixPushdownAutomatonGlushkovV3.cpp
- *
- *  Created on: 26. 7. 2017
- *	  Author: Tomas Pecka
- */
-
-#include "ToPostfixPushdownAutomatonGlushkovV3.h"
-
-#include <automaton/Automaton.h>
-#include <alphabet/BottomOfTheStackSymbol.h>
-#include <alphabet/EndSymbol.h>
-
-#include <global/GlobalData.h>
-#include <registration/AlgoRegistration.hpp>
-
-#include "../glushkov/GlushkovFollowV3.h"
-#include "../glushkov/GlushkovIndexate.h"
-#include "../glushkov/GlushkovFirst.h"
-#include "../glushkov/GlushkovSubstitutionMap.h"
-
-namespace rte {
-
-namespace convert {
-
-automaton::Automaton ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::RTE & rte ) {
-	return dispatch ( rte.getData ( ) );
-}
-
-template < class SymbolType, class RankType >
-bool ToPostfixPushdownAutomatonGlushkovV3::isSubstSymbolPresent ( const std::set < std::ranked_symbol < SymbolType, RankType > > & container, const TAlphabet < SymbolType, RankType > & substAlphabet ) {
-	std::vector < std::ranked_symbol < > > intersection;
-	std::set_intersection ( container.begin ( ), container.end ( ), substAlphabet.begin ( ), substAlphabet.end ( ), std::back_inserter ( intersection ) );
-	return intersection.size ( ) > 0;
-}
-
-template < class SymbolType, class RankType >
-automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType >
-ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) {
-
-	 // step 1; index RTE
-	rte::FormalRTE < > indexedRTE = rte::GlushkovIndexate::index ( rte );
-
-	 // step 2; compute:
-	 // - first set
-	const std::set < std::ranked_symbol < > > firstSet = rte::GlushkovFirst::first ( indexedRTE );
-
-	 // - follow set for every element of (non-indexed) RTE alphabet element
-	const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > substMapTree = GlushkovSubstitutionMap::substMap ( indexedRTE );
-	std::map < std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > > followSet;
-
-	for ( const std::ranked_symbol < > & symbol : indexedRTE.getAlphabet ( ) )
-		followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollowV3::follow ( indexedRTE, symbol, substMapTree ) ) );
-
-	/* check for exceptions -> there must be NO substitution symbol in first set */
-	if ( isSubstSymbolPresent ( firstSet, rte.getSubstitutionAlphabet ( ) ) )
-		throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in the first set" );
-	/* check end */
-
-	/* check for exceptions -> there must be NO substitution symbol in follow sets */
-	for ( const std::pair < const std::ranked_symbol < SymbolType, RankType >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > > & kv : followSet )
-		for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) // TFollowTuple = vector < set < ranked_symbol > >
-			for ( const std::set < std::ranked_symbol < SymbolType, RankType > > & followTupleElem : followTuple )
-				if ( isSubstSymbolPresent ( followTupleElem, rte.getSubstitutionAlphabet ( ) ) )
-					throw exception::CommonException ( "GlushkovRTE: Substitution symbol appeared in a follow set" );
-	/* check end */
-
-	 // step 3; create PDA (w/o transitions yet) and initialize input alphabet = (non-indexed) RTE alphabet and END symbol
-	DefaultStateType q = DefaultStateType ( 'q' );
-	DefaultStateType f = DefaultStateType ( 'f' );
-
-	auto BotS = std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >::template from < alphabet::BottomOfTheStackSymbol > ( );
-	automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType > automaton ( q, BotS );
-
-	automaton.addState ( f );
-	automaton.addFinalState ( f );
-
-	for ( const std::ranked_symbol < > & symbol : rte.getAlphabet ( ) )
-		automaton.addInputSymbol ( symbol.getSymbol ( ) );
-
-	automaton.addInputSymbol ( alphabet::EndSymbol::instance < DefaultSymbolType > ( ) );
-
-	// step 4; create pushdown store alphabet;
-
-	// simple
-	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) )
-		automaton.addPushdownStoreSymbol ( std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > ( { symb } ) );
-
-	// complex
-	for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) {
-		if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) ) { 
-			for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) {
-				automaton.addPushdownStoreSymbol ( kv2.second );
-			}
-		}
-	}
-
-	/* DEBUG */
-	if ( common::GlobalData::verbose ) {
-		std::cerr << "RTE:" << std::endl;
-
-		for ( const auto & symbol : indexedRTE.getAlphabet ( ) )
-			std::cerr << "\t" << symbol << std::endl;
-
-		std::cerr << std::endl;
-
-		std::cerr << "First(RTE):" << std::endl;
-
-		for ( const auto & symbol : firstSet )
-			std::cerr << "\t" << symbol << std::endl;
-
-		std::cerr << std::endl;
-
-		// std::map < std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > > followSet;
-		for ( const std::pair < const std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > >& kv : followSet ) {
-			std::cerr << "Follow(RTE, " << kv.first << "):" << std::endl;
-
-			if ( kv.second.empty ( ) )
-				std::cerr << "\t" << "{}" << std::endl;
-
-			for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) { // TFollowTuple = vector < set < ranked_symbol > >
-				std::cerr << " \t - FollowTuple:" << std::endl;
-				for ( const std::set < std::ranked_symbol < > > & child : followTuple )
-					std::cerr << "\t\t - " << child << std::endl;
-
-				std::cerr << std::endl;
-			}
-
-			std::cerr << std::endl;
-		}
-
-		std::cerr << "---------------------------------------------------------" << std::endl;
-		std::cerr << "PDA:" << std::endl;
-		std::cerr << "pds symbols" << std::endl;
-
-		for ( const auto & symb : automaton.getPushdownStoreAlphabet ( ) )
-			std::cerr << "\t" << symb << std::endl;
-		std::cerr << std::endl;
-	}
-	/* DEBUG END */
-
-
-	/* TRANSITIONS */
-	// Pattern 3 and 2
-	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) {
-		if ( symb.getRank ( ) == primitive::Unsigned ( 0 ) ) {
-			std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > push;
-			push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
-
-			if ( common::GlobalData::verbose ) {
-				std::cerr << "Transition 3: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
-					"\t" << "[]" << std::endl <<
-					"\t ->" << std::endl <<
-					"\t" << push << std::endl << std::endl;
-			}
-			automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, push );
-		} else {
-			for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : followSet [ symb ] ) { //tuple = vector < set < symb > >
-				std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push;
-
-				/*
-				for ( const auto & e : symbFollowTuple )
-				   pop.push_back ( e );
-				std::reverse ( pop.begin ( ), pop.end ( ) ); // <------------ WTF. CRASHES HERE // FIXME
-				*/
-				for ( const auto & e : followTuple )
-					pop.insert ( pop.begin ( ), e );
-
-				push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
-
-				if ( common::GlobalData::verbose ) {
-					std::cerr << "Transition 2: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
-						"\t" << pop << std::endl <<
-						"\t ->" << std::endl <<
-						"\t" << push << std::endl << std::endl;
-				}
-				automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push );
-			}
-		}
-	}
-
-	// Pattern 1
-	for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) {
-		for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) {
-			if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) == nullptr ) // not a SubstSymbol node
-				continue;
-
-			for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) {
-				if ( kv2.second.count ( symb ) == 0 ) 
-					continue;
-
-				for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & symbFollowTuple : followSet [ symb ] ) {
-					std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push;
-
-					if ( ( size_t ) symb.getRank ( ) > 0 ) {
-						for ( const auto & e : symbFollowTuple )
-							pop.insert ( pop.begin ( ), e );
-					}
-
-					push.push_back( kv2.second );
-
-					if ( common::GlobalData::verbose ) {
-						std::cerr << "Transition 1" << ( pop.empty() ? "a" : "b" ) <<  ": " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl <<
-							"\t" << pop << std::endl <<
-							"\t ->" << std::endl <<
-							"\t" << push << std::endl << std::endl;
-					}
-
-					automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push );
-				}
-			}
-		}
-	}
-
-	// Final
-	for ( const std::ranked_symbol < > & symb : firstSet ) {
-		std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop;
-		pop.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } );
-		pop.push_back ( BotS );
-		automaton.addTransition ( q, alphabet::EndSymbol::instance < DefaultSymbolType > ( ), pop, f, { } );
-	}
-	/* TRANSITIONS END */
-
-	return automaton;
-}
-
-auto ToAutomatonGlushkovFormalRegExpV3 = registration::OverloadRegister < ToPostfixPushdownAutomatonGlushkovV3,
-			automaton::NPDA < DefaultSymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < alib::Object, primitive::Unsigned > > >, DefaultStateType >,
-			rte::FormalRTE < > > ( ToPostfixPushdownAutomatonGlushkovV3::convert );
-
-} /* namespace convert */
-
-} /* namespace rte */
diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.h b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.h
deleted file mode 100644
index f6f888faff4599166ba9b5061294a7130f6ab568..0000000000000000000000000000000000000000
--- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * ToPostfixPushdownAutomatonGlushkovV3.h
- *
- *  Created on: 26. 7. 2017
- *	  Author: Tomas Pecka
- */
-
-#ifndef TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_V3_H_
-#define TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_V3_H_
-
-#include <core/multipleDispatch.hpp>
-#include <map>
-
-#include <automaton/PDA/NPDA.h>
-
-#include <rte/RTE.h>
-#include <rte/formal/FormalRTE.h>
-
-#include <container/ObjectsVariant.h>
-#include <container/ObjectsSet.h>
-
-namespace rte {
-
-namespace convert {
-
-/**
- * Converts regular tree expression to real-time height-deterministic pda
- * Source: Master Thesis, Pecka Tomas, CTU FIT, 2016, chapter 4.2
- */
-class ToPostfixPushdownAutomatonGlushkovV3 : public std::SingleDispatch < ToPostfixPushdownAutomatonGlushkovV3, automaton::Automaton, const rte::RTEBase & > {
-private:
-	// --------------------------------------------------------------------
-
-	template < class SymbolType, class RankType >
-	using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >;
-
-	// --------------------------------------------------------------------
-
-	template < class SymbolType, class RankType >
-	static bool isSubstSymbolPresent ( const std::set < std::ranked_symbol < SymbolType, RankType > > & container, const TAlphabet < SymbolType, RankType > & substAlphabet );
-public:
-	/**
-	 * Performs conversion.
-	 * @param re Original regular tree expression.
-	 * @return rhNPDA equivalent to original regular expression.
-	 */
-	static automaton::Automaton convert ( const rte::RTE & rte );
-
-	template < class SymbolType, class RankType >
-	static automaton::NPDA < SymbolType, DefaultEpsilonType, std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > >, DefaultStateType > convert ( const rte::FormalRTE < > & rte );
-};
-
-} /* namespace convert */
-
-} /* namespace rte */
-
-#endif /* TO_POSTFIX_PUSHDOWN_AUTOMATON_GLUSHKOV_V3_H_ */
diff --git a/alib2algo/src/rte/glushkov/GlushkovFollow.h b/alib2algo/src/rte/glushkov/GlushkovFollow.h
index c03d5e5ff1b2886f2941be5dd2d0c2bfa500aef9..88a9f364e9f3a1e4dcd3884be4e8169f56daa61d 100644
--- a/alib2algo/src/rte/glushkov/GlushkovFollow.h
+++ b/alib2algo/src/rte/glushkov/GlushkovFollow.h
@@ -1,7 +1,7 @@
 /*
  * GlushkovFollow.h
  *
- *  Created on: 14. 4. 2016
+ *  Created on: 26. 7. 2017
  *	  Author: Tomas Pecka
  */
 
@@ -27,155 +27,86 @@ namespace rte {
 class GlushkovFollow {
 
 	// --------------------------------------------------------------------
+public:
 
 	template < class SymbolType, class RankType >
-	using TSubstMap = std::map < std::ranked_symbol < SymbolType, RankType >, std::set < std::ranked_symbol < SymbolType, RankType > > >;
+	using TFollowTuple = std::vector < std::set < std::ranked_symbol < SymbolType, RankType > > >;
 
 	template < class SymbolType, class RankType >
 	using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >;
 
-	// --------------------------------------------------------------------
-
+private:
 	template < class SymbolType, class RankType >
-	static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 );
-
-	template < class SymbolType, class RankType >
-	static void preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap );
+	using TSubstMap = std::map < std::ranked_symbol < SymbolType, RankType >, std::set < std::ranked_symbol < SymbolType, RankType > > >;
 
-	template < class T >
-	static std::vector < std::vector < T > > cartesian ( const std::vector < std::vector < T > > & input );
+	// --------------------------------------------------------------------
 
-	template < class T >
-	static void cartesian_rec ( const std::vector < std::vector < T > > & input, std::vector < std::vector < T > > & ret, std::vector < T > & current, size_t depth );
+	template < class SymbolType, class RankType >
+	static std::set < TFollowTuple < SymbolType, RankType > > replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 );
 
 public:
 	/**
 	 * @param re rte to probe
 	 * @param symbol FormalRTESymbol for which we need the follow(), i.e., Follow(RTE, symbol)
+	 * @param substMapTree Tree substitution mapping from, rte::GlushkovSubstitutionMap::substMap
 	 * @return all symbols that can follow specific symbol in word
 	 */
 	template < class SymbolType, class RankType >
-	static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > follow ( const rte::FormalRTE < SymbolType, RankType > & re, const std::ranked_symbol < SymbolType, RankType > & symbol );
+	static std::set < TFollowTuple < SymbolType, RankType > > follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree );
 
 	template < class SymbolType, class RankType >
 	class Formal {
 	public:
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
-		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
+
 	};
 
 };
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol ) {
-	TSubstMap < SymbolType, RankType > subMap;
-
-	 /* Init substitution map, ie \forall a \in K: sub[a] = \emptyset */
-	for ( const std::ranked_symbol < SymbolType, RankType > & ssymb : rte.getSubstitutionAlphabet ( ) )
-		subMap.insert ( std::make_pair ( ssymb, TAlphabet < SymbolType, RankType > { } ) );
-
-	 /* recursively compute follow */
-	return rte.getRTE ( ).getStructure ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), subMap );
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree ) {
+	return rte.getRTE ( ).getStructure ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), substMapTree );
 }
 
 // -----------------------------------------------------------------------------
 
-template < class T >
-void GlushkovFollow::cartesian_rec ( const std::vector < std::vector < T > > & input, std::vector < std::vector < T > > & ret, std::vector < T > & current, size_t depth ) {
-	if ( depth == input.size ( ) )
-		ret.push_back ( current );
-	else
-		for ( size_t i = 0; i < input[depth].size ( ); i++ ) {
-			current[depth] = input[depth][i];
-			cartesian_rec ( input, ret, current, depth + 1 );
-		}
-}
-
-template < class T >
-std::vector < std::vector < T > > GlushkovFollow::cartesian ( const std::vector < std::vector < T > > & input ) {
-	std::vector < std::vector < T > > ret;
-	std::vector < T > current ( input.size ( ), T ( 0, 0 ) );
-
-	cartesian_rec ( input, ret, current, 0 );
-
-	return ret;
-}
-
-/**
- * Preprocessing:
- *  - Let k1, k2 be elements of alphabet K.
- *  - If k1 is an element of substMap[k2], then copy content of substMap[k1] into substMap[k2]
- */
-template < class SymbolType, class RankType >
-void GlushkovFollow::preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
-	for ( bool change = true; change; change = false )
-		for ( std::pair < const std::ranked_symbol < SymbolType, RankType >, TAlphabet < SymbolType, RankType > > & kv : subMap ) {
-			TAlphabet < SymbolType, RankType > & substSet = kv.second;
-
-			for ( auto eIter = substSet.begin ( ); eIter != substSet.end ( ); ) {
-				if ( alphabetK.count ( * eIter ) == 0 ) {
-					++eIter;
-				} else {
-					auto it = subMap.find ( * eIter );
-					size_t oldSize = substSet.size ( );
-					substSet.insert ( it->second.begin ( ), it->second.end ( ) );
-					change = ( oldSize != substSet.size ( ) ); // something was added
-					eIter = substSet.erase ( eIter );
-				}
-			}
-		}
-}
-
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 ) {
-	TSubstMap < SymbolType, RankType > subMap ( subMap2 );
-	preprocessSubMap ( alphabetK, subMap );
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & children, const TSubstMap < SymbolType, RankType > & subMap ) {
+	TFollowTuple < SymbolType, RankType > follow;
 
-	std::vector < std::vector < std::ranked_symbol < SymbolType, RankType > > > input;
-
-	for ( const std::ranked_symbol < SymbolType, RankType > & e : follow ) {
+	for ( const std::ranked_symbol < SymbolType, RankType > & e : children ) {
 		if ( alphabetK.count ( e ) > 0 )
-			input.push_back ( std::vector < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) );
+			follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) );
 		else
-			input.push_back ( std::vector < std::ranked_symbol < SymbolType, RankType > > { e } );
+			follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { e } );
 	}
 
-	 /* now do the cartesian product on "input" */
-	std::vector < std::vector < std::ranked_symbol < SymbolType, RankType > > > followSet = cartesian ( input );
-	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( followSet.begin ( ), followSet.end ( ) );
+	return std::set < TFollowTuple < SymbolType, RankType > > { follow };
 }
 
 // -----------------------------------------------------------------------------
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
-	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret, tmp;
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
+	std::set < TFollowTuple < SymbolType, RankType > > ret, tmp;
 
-	tmp = node.getLeftElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+	tmp = node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 	ret.insert ( tmp.begin ( ), tmp.end ( ) );
 
-	tmp = node.getRightElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+	tmp = node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 	ret.insert ( tmp.begin ( ), tmp.end ( ) );
 
 	return ret;
 }
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
-
-	TSubstMap < SymbolType, RankType > subMap2 ( subMap );
-	auto itMap = subMap2.find ( node.getSubstitutionSymbol ( ).getSymbol ( ) );
-
-	itMap->second.clear ( );
-
-	for ( const auto & s : node.getRightElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) )
-		itMap->second.insert ( s );
-
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
 	/*
 	 * E sub F
 	 *   1. if symbolF in F subtree, then Follow(F, symbolF);
@@ -183,26 +114,20 @@ std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > Glushko
 	 */
 
 	if ( node.getLeftElement ( ).template accept < bool, GlushkovPos::Formal < SymbolType, RankType > > ( symbolF ) )
-		return node.getLeftElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap2 );
+		return node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 	else
-		return node.getRightElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+		return node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 }
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
-
-	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret;
-
-	for ( const auto & s : node.getElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) )
-		subMap[node.getSubstitutionSymbol ( ).getSymbol ( )].insert ( s );
-
-	return node.getElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
+	return node.getElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 }
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
 
-	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret, tmp;
+	std::set < TFollowTuple < SymbolType, RankType > > ret, tmp;
 
 	if ( symbolF == node.getSymbol ( ) ) {
 		std::vector < std::ranked_symbol < SymbolType, RankType > > children;
@@ -210,11 +135,11 @@ std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > Glushko
 		for ( const std::smart_ptr < const rte::FormalRTESymbol < SymbolType, RankType > > & c : node.getElements ( ) )
 			children.push_back ( c->getSymbol ( ) );
 
-		return replaceConstants ( alphabetK, children, subMap );
+		return replaceConstants ( alphabetK, children, substMapTree.at( & node ));
 	}
 
 	for ( const auto & c : node.getElements ( ) ) {
-		tmp = c->template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+		tmp = c->template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollow::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
 		ret.insert ( tmp.begin ( ), tmp.end ( ) );
 	}
 
@@ -222,13 +147,13 @@ std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > Glushko
 }
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) {
-	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( );
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) {
+	return std::set < TFollowTuple < SymbolType, RankType > > ( );
 }
 
 template < class SymbolType, class RankType >
-std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollow::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) {
-	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( );
+std::set < GlushkovFollow::TFollowTuple < SymbolType, RankType > > GlushkovFollow::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) {
+	return std::set < TFollowTuple < SymbolType, RankType > > ( );
 }
 
 } /* namespace rte */
diff --git a/alib2algo/src/rte/glushkov/GlushkovFollowNaive.h b/alib2algo/src/rte/glushkov/GlushkovFollowNaive.h
new file mode 100644
index 0000000000000000000000000000000000000000..cfeb0dae9619b50e3c07688a011a7807cb094fb7
--- /dev/null
+++ b/alib2algo/src/rte/glushkov/GlushkovFollowNaive.h
@@ -0,0 +1,236 @@
+/*
+ * GlushkovFollowNaive.h
+ *
+ *  Created on: 14. 4. 2016
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef RTE_GLUSHKOV_FOLLOW_NAIVE_H_
+#define RTE_GLUSHKOV_FOLLOW_NAIVE_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <rte/formal/FormalRTE.h>
+#include <rte/formal/FormalRTEElements.h>
+
+#include <alphabet/RankedSymbol.h>
+
+#include "GlushkovFirst.h"
+#include "GlushkovPos.h"
+#include <iterator>
+#include <vector>
+
+namespace rte {
+
+class GlushkovFollowNaive {
+
+	// --------------------------------------------------------------------
+
+	template < class SymbolType, class RankType >
+	using TSubstMap = std::map < std::ranked_symbol < SymbolType, RankType >, std::set < std::ranked_symbol < SymbolType, RankType > > >;
+
+	template < class SymbolType, class RankType >
+	using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >;
+
+	// --------------------------------------------------------------------
+
+	template < class SymbolType, class RankType >
+	static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 );
+
+	template < class SymbolType, class RankType >
+	static void preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap );
+
+	template < class T >
+	static std::vector < std::vector < T > > cartesian ( const std::vector < std::vector < T > > & input );
+
+	template < class T >
+	static void cartesian_rec ( const std::vector < std::vector < T > > & input, std::vector < std::vector < T > > & ret, std::vector < T > & current, size_t depth );
+
+public:
+	/**
+	 * @param re rte to probe
+	 * @param symbol FormalRTESymbol for which we need the follow(), i.e., Follow(RTE, symbol)
+	 * @return all symbols that can follow specific symbol in word
+	 */
+	template < class SymbolType, class RankType >
+	static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > follow ( const rte::FormalRTE < SymbolType, RankType > & re, const std::ranked_symbol < SymbolType, RankType > & symbol );
+
+	template < class SymbolType, class RankType >
+	class Formal {
+	public:
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+		static std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM );
+	};
+
+};
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol ) {
+	TSubstMap < SymbolType, RankType > subMap;
+
+	 /* Init substitution map, ie \forall a \in K: sub[a] = \emptyset */
+	for ( const std::ranked_symbol < SymbolType, RankType > & ssymb : rte.getSubstitutionAlphabet ( ) )
+		subMap.insert ( std::make_pair ( ssymb, TAlphabet < SymbolType, RankType > { } ) );
+
+	 /* recursively compute follow */
+	return rte.getRTE ( ).getStructure ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), subMap );
+}
+
+// -----------------------------------------------------------------------------
+
+template < class T >
+void GlushkovFollowNaive::cartesian_rec ( const std::vector < std::vector < T > > & input, std::vector < std::vector < T > > & ret, std::vector < T > & current, size_t depth ) {
+	if ( depth == input.size ( ) )
+		ret.push_back ( current );
+	else
+		for ( size_t i = 0; i < input[depth].size ( ); i++ ) {
+			current[depth] = input[depth][i];
+			cartesian_rec ( input, ret, current, depth + 1 );
+		}
+}
+
+template < class T >
+std::vector < std::vector < T > > GlushkovFollowNaive::cartesian ( const std::vector < std::vector < T > > & input ) {
+	std::vector < std::vector < T > > ret;
+	std::vector < T > current ( input.size ( ), T ( 0, 0 ) );
+
+	cartesian_rec ( input, ret, current, 0 );
+
+	return ret;
+}
+
+/**
+ * Preprocessing:
+ *  - Let k1, k2 be elements of alphabet K.
+ *  - If k1 is an element of substMap[k2], then copy content of substMap[k1] into substMap[k2]
+ */
+template < class SymbolType, class RankType >
+void GlushkovFollowNaive::preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+	for ( bool change = true; change; change = false )
+		for ( std::pair < const std::ranked_symbol < SymbolType, RankType >, TAlphabet < SymbolType, RankType > > & kv : subMap ) {
+			TAlphabet < SymbolType, RankType > & substSet = kv.second;
+
+			for ( auto eIter = substSet.begin ( ); eIter != substSet.end ( ); ) {
+				if ( alphabetK.count ( * eIter ) == 0 ) {
+					++eIter;
+				} else {
+					auto it = subMap.find ( * eIter );
+					size_t oldSize = substSet.size ( );
+					substSet.insert ( it->second.begin ( ), it->second.end ( ) );
+					change = ( oldSize != substSet.size ( ) ); // something was added
+					eIter = substSet.erase ( eIter );
+				}
+			}
+		}
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 ) {
+	TSubstMap < SymbolType, RankType > subMap ( subMap2 );
+	preprocessSubMap ( alphabetK, subMap );
+
+	std::vector < std::vector < std::ranked_symbol < SymbolType, RankType > > > input;
+
+	for ( const std::ranked_symbol < SymbolType, RankType > & e : follow ) {
+		if ( alphabetK.count ( e ) > 0 )
+			input.push_back ( std::vector < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) );
+		else
+			input.push_back ( std::vector < std::ranked_symbol < SymbolType, RankType > > { e } );
+	}
+
+	 /* now do the cartesian product on "input" */
+	std::vector < std::vector < std::ranked_symbol < SymbolType, RankType > > > followSet = cartesian ( input );
+	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( followSet.begin ( ), followSet.end ( ) );
+}
+
+// -----------------------------------------------------------------------------
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret, tmp;
+
+	tmp = node.getLeftElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+	ret.insert ( tmp.begin ( ), tmp.end ( ) );
+
+	tmp = node.getRightElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+	ret.insert ( tmp.begin ( ), tmp.end ( ) );
+
+	return ret;
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+
+	TSubstMap < SymbolType, RankType > subMap2 ( subMap );
+	auto itMap = subMap2.find ( node.getSubstitutionSymbol ( ).getSymbol ( ) );
+
+	itMap->second.clear ( );
+
+	for ( const auto & s : node.getRightElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) )
+		itMap->second.insert ( s );
+
+	/*
+	 * E sub F
+	 *   1. if symbolF in F subtree, then Follow(F, symbolF);
+	 *   2. if symbolF in E subtree, then Follow(E, symbolF);
+	 */
+
+	if ( node.getLeftElement ( ).template accept < bool, GlushkovPos::Formal < SymbolType, RankType > > ( symbolF ) )
+		return node.getLeftElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap2 );
+	else
+		return node.getRightElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+
+	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret;
+
+	for ( const auto & s : node.getElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) )
+		subMap[node.getSubstitutionSymbol ( ).getSymbol ( )].insert ( s );
+
+	return node.getElement ( ).template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) {
+
+	std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ret, tmp;
+
+	if ( symbolF == node.getSymbol ( ) ) {
+		std::vector < std::ranked_symbol < SymbolType, RankType > > children;
+
+		for ( const std::smart_ptr < const rte::FormalRTESymbol < SymbolType, RankType > > & c : node.getElements ( ) )
+			children.push_back ( c->getSymbol ( ) );
+
+		return replaceConstants ( alphabetK, children, subMap );
+	}
+
+	for ( const auto & c : node.getElements ( ) ) {
+		tmp = c->template accept < std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > >, GlushkovFollowNaive::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap );
+		ret.insert ( tmp.begin ( ), tmp.end ( ) );
+	}
+
+	return ret;
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) {
+	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( );
+}
+
+template < class SymbolType, class RankType >
+std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > GlushkovFollowNaive::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) {
+	return std::set < std::vector < std::ranked_symbol < SymbolType, RankType > > > ( );
+}
+
+} /* namespace rte */
+
+#endif /* RTE_GLUSHKOV_FOLLOW_NAIVE_H_ */
diff --git a/alib2algo/src/rte/glushkov/GlushkovFollowV3.h b/alib2algo/src/rte/glushkov/GlushkovFollowV3.h
deleted file mode 100644
index 4c33e1f33f271a5c96a9d2f21c57c3d44e21a1f2..0000000000000000000000000000000000000000
--- a/alib2algo/src/rte/glushkov/GlushkovFollowV3.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * GlushkovFollowV3.h
- *
- *  Created on: 26. 7. 2017
- *	  Author: Tomas Pecka
- */
-
-#ifndef RTE_GLUSHKOV_FOLLOW_V3_H_
-#define RTE_GLUSHKOV_FOLLOW_V3_H_
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include <rte/formal/FormalRTE.h>
-#include <rte/formal/FormalRTEElements.h>
-
-#include <alphabet/RankedSymbol.h>
-
-#include "GlushkovFirst.h"
-#include "GlushkovPos.h"
-#include <iterator>
-#include <vector>
-
-namespace rte {
-
-class GlushkovFollowV3 {
-
-	// --------------------------------------------------------------------
-public:
-
-	template < class SymbolType, class RankType >
-	using TFollowTuple = std::vector < std::set < std::ranked_symbol < SymbolType, RankType > > >;
-
-	template < class SymbolType, class RankType >
-	using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >;
-
-private:
-	template < class SymbolType, class RankType >
-	using TSubstMap = std::map < std::ranked_symbol < SymbolType, RankType >, std::set < std::ranked_symbol < SymbolType, RankType > > >;
-
-	// --------------------------------------------------------------------
-
-	template < class SymbolType, class RankType >
-	static std::set < TFollowTuple < SymbolType, RankType > > replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 );
-
-public:
-	/**
-	 * @param re rte to probe
-	 * @param symbol FormalRTESymbol for which we need the follow(), i.e., Follow(RTE, symbol)
-	 * @param substMapTree Tree substitution mapping from, rte::GlushkovSubstitutionMap::substMap
-	 * @return all symbols that can follow specific symbol in word
-	 */
-	template < class SymbolType, class RankType >
-	static std::set < TFollowTuple < SymbolType, RankType > > follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree );
-
-	template < class SymbolType, class RankType >
-	class Formal {
-	public:
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-		static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree );
-
-	};
-
-};
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree ) {
-	return rte.getRTE ( ).getStructure ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), substMapTree );
-}
-
-// -----------------------------------------------------------------------------
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & children, const TSubstMap < SymbolType, RankType > & subMap ) {
-	TFollowTuple < SymbolType, RankType > follow;
-
-	for ( const std::ranked_symbol < SymbolType, RankType > & e : children ) {
-		if ( alphabetK.count ( e ) > 0 )
-			follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) );
-		else
-			follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { e } );
-	}
-
-	return std::set < TFollowTuple < SymbolType, RankType > > { follow };
-}
-
-// -----------------------------------------------------------------------------
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
-	std::set < TFollowTuple < SymbolType, RankType > > ret, tmp;
-
-	tmp = node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-	ret.insert ( tmp.begin ( ), tmp.end ( ) );
-
-	tmp = node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-	ret.insert ( tmp.begin ( ), tmp.end ( ) );
-
-	return ret;
-}
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
-	/*
-	 * E sub F
-	 *   1. if symbolF in F subtree, then Follow(F, symbolF);
-	 *   2. if symbolF in E subtree, then Follow(E, symbolF);
-	 */
-
-	if ( node.getLeftElement ( ).template accept < bool, GlushkovPos::Formal < SymbolType, RankType > > ( symbolF ) )
-		return node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-	else
-		return node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-}
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
-	return node.getElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-}
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) {
-
-	std::set < TFollowTuple < SymbolType, RankType > > ret, tmp;
-
-	if ( symbolF == node.getSymbol ( ) ) {
-		std::vector < std::ranked_symbol < SymbolType, RankType > > children;
-
-		for ( const std::smart_ptr < const rte::FormalRTESymbol < SymbolType, RankType > > & c : node.getElements ( ) )
-			children.push_back ( c->getSymbol ( ) );
-
-		return replaceConstants ( alphabetK, children, substMapTree.at( & node ));
-	}
-
-	for ( const auto & c : node.getElements ( ) ) {
-		tmp = c->template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree );
-		ret.insert ( tmp.begin ( ), tmp.end ( ) );
-	}
-
-	return ret;
-}
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) {
-	return std::set < TFollowTuple < SymbolType, RankType > > ( );
-}
-
-template < class SymbolType, class RankType >
-std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) {
-	return std::set < TFollowTuple < SymbolType, RankType > > ( );
-}
-
-} /* namespace rte */
-
-#endif /* RTE_GLUSHKOV_FOLLOW_V3_H_ */
diff --git a/tests.glushkovrte_v3.sh b/tests.glushkovrte_naive.sh
similarity index 96%
rename from tests.glushkovrte_v3.sh
rename to tests.glushkovrte_naive.sh
index 55736a0135932f855835c60e144288aa026d3656..3689c7fe0b0b73a3fc68184c942e47141d2e2919 100755
--- a/tests.glushkovrte_v3.sh
+++ b/tests.glushkovrte_naive.sh
@@ -158,7 +158,7 @@ function run {
 		#echo $GEN_FILE
 		#echo $AUTOMATON_FILE
 
-		./aconversions2 -t pda -a glushkovrtev3 -i $RTE_FILE 2>/dev/null | ./adeterminize2 > $AUTOMATON_FILE
+		./aconversions2 -t pda -a glushkovrtenaive -i $RTE_FILE 2>/dev/null | ./adeterminize2 > $AUTOMATON_FILE
 
 		for i in `seq 1 $TESTCASE_ITERATIONS`; do
 			runAcceptTest $GEN_FILE $AUTOMATON_FILE $RTE_FILE