diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
index d07cc9d01a5615a88c66a2ab178577a6b524ea91..dcb3c015bfd712178f64a93da096aadbb166b0c6 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
@@ -6,104 +6,17 @@
  */
 
 #include "ExactSubtreeMatchingAutomaton.h"
-#include <tree/ranked/PrefixRankedBarTree.h>
-#include <tree/ranked/PrefixRankedTree.h>
-#include <tree/ranked/RankedTree.h>
-
-#include <automaton/PDA/InputDrivenNPDA.h>
-#include <automaton/TA/NFTA.h>
-
-#include <alphabet/BottomOfTheStackSymbol.h>
-
-#include <alib/deque>
 #include <registration/AlgoRegistration.hpp>
 
 namespace arbology {
 
 namespace exact {
 
-automaton::InputDrivenNPDA < > ExactSubtreeMatchingAutomaton::construct ( const tree::PrefixRankedTree < > & pattern ) {
-	automaton::InputDrivenNPDA < > res ( DefaultStateType ( 0 ), DefaultSymbolType ( 'S' ) );
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
-		res.addInputSymbol ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ) );
-		res.setPushdownStoreOperation ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'S' ) ), ext::vector < DefaultSymbolType > ( ( size_t ) symbol.getRank ( ), DefaultSymbolType ( 'S' ) ) );
-	}
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
-		res.addTransition ( DefaultStateType ( 0 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), DefaultStateType ( 0 ) );
-	}
-
-	int i = 1;
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getContent ( ) ) {
-		res.addState ( DefaultStateType ( i ) );
-		res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), DefaultStateType ( i ) );
-		i++;
-	}
-
-	res.addFinalState ( DefaultStateType ( i - 1 ) );
-	return res;
-}
-
-auto ExactSubtreeMatchingAutomatonPrefixRankedTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::InputDrivenNPDA < >, const tree::PrefixRankedTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
-
-automaton::InputDrivenNPDA < > ExactSubtreeMatchingAutomaton::construct ( const tree::PrefixRankedBarTree < > & pattern ) {
-	automaton::InputDrivenNPDA < > res ( DefaultStateType ( 0 ), alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ) );
-
-	res.setPushdownStoreAlphabet ( { alphabet::BottomOfTheStackSymbol::instance < DefaultSymbolType > ( ), DefaultSymbolType ( 'S' ) } );
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
-		res.addInputSymbol ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ) );
-
-		if ( pattern.getBars ( ).count ( symbol ) )
-			res.setPushdownStoreOperation ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'S' ) ), ext::vector < DefaultSymbolType > { } );
-		else
-			res.setPushdownStoreOperation ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), ext::vector < DefaultSymbolType > { }, ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'S' ) ) );
-	}
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
-		res.addTransition ( DefaultStateType ( 0 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), DefaultStateType ( 0 ) );
-	}
-
-	int i = 1;
-
-	for ( const common::ranked_symbol < > & symbol : pattern.getContent ( ) ) {
-		res.addState ( DefaultStateType ( i ) );
-		res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), DefaultStateType ( i ) );
-		i++;
-	}
-
-	res.addFinalState ( DefaultStateType ( i - 1 ) );
-	return res;
-}
-
-auto ExactSubtreeMatchingAutomatonPrefixRankedBarTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::InputDrivenNPDA < >, const tree::PrefixRankedBarTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
-
-DefaultStateType constructRecursive ( const ext::tree < common::ranked_symbol < > > & node, automaton::NFTA < > & res, int & nextState ) {
-	ext::vector < DefaultStateType > states;
-
-	states.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
-
-	for ( const ext::tree < common::ranked_symbol < > > & child : node.getChildren ( ) )
-		states.push_back ( constructRecursive ( child, res, nextState ) );
-
-	DefaultStateType state = DefaultStateType ( nextState++ );
-	res.addState ( state );
-	res.addTransition ( node.getData ( ), states, state );
-	return state;
-}
-
-automaton::NFTA < > ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
-	automaton::NFTA < > res;
+auto ExactSubtreeMatchingAutomatonPrefixRankedTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, unsigned >, const tree::PrefixRankedTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
 
-	res.setInputAlphabet ( pattern.getAlphabet ( ) );
-	int nextState = 0;
-	res.addFinalState ( constructRecursive ( pattern.getContent ( ), res, nextState ) );
-	return res;
-}
+auto ExactSubtreeMatchingAutomatonPrefixRankedBarTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, unsigned >, const tree::PrefixRankedBarTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
 
-auto ExactSubtreeMatchingAutomatonRankedTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::NFTA < >, const tree::RankedTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
+auto ExactSubtreeMatchingAutomatonRankedTree = registration::AbstractRegister < ExactSubtreeMatchingAutomaton, automaton::NFTA < DefaultSymbolType, DefaultRankType, unsigned >, const tree::RankedTree < > & > ( ExactSubtreeMatchingAutomaton::construct );
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
index 7ca9f9e0370c0b3cb735b9defe0b20c6f335d0d1..dcca618e0b8a9c6272b605a153c7f332385865a5 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
@@ -8,8 +8,14 @@
 #ifndef _EXACT_SUBTREE_MATCHING_AUTOMATON_H__
 #define _EXACT_SUBTREE_MATCHING_AUTOMATON_H__
 
-#include <automaton/AutomatonFeatures.h>
-#include <tree/TreeFeatures.h>
+#include <tree/ranked/PrefixRankedBarTree.h>
+#include <tree/ranked/PrefixRankedTree.h>
+#include <tree/ranked/RankedTree.h>
+
+#include <automaton/PDA/InputDrivenNPDA.h>
+#include <automaton/TA/NFTA.h>
+
+#include <alphabet/BottomOfTheStackSymbol.h>
 
 namespace arbology {
 
@@ -21,12 +27,98 @@ public:
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
 	 */
-	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedTree < > & pattern );
-	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedBarTree < > & pattern );
-	static automaton::NFTA < > construct ( const tree::RankedTree < > & pattern );
+	template < class SymbolType, class RankType >
+	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > construct ( const tree::PrefixRankedTree < SymbolType, RankType > & pattern );
+
+	template < class SymbolType, class RankType >
+	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & pattern );
+
+	template < class SymbolType, class RankType >
+	static automaton::NFTA < SymbolType, RankType, unsigned > construct ( const tree::RankedTree < SymbolType, RankType > & pattern );
 
 };
 
+template < class SymbolType, class RankType >
+automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > ExactSubtreeMatchingAutomaton::construct ( const tree::PrefixRankedTree < SymbolType, RankType > & pattern ) {
+	automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > res ( 0, 'S' );
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) {
+		res.addInputSymbol ( symbol );
+		res.setPushdownStoreOperation ( symbol, ext::vector < char > ( 1, 'S' ), ext::vector < char > ( ( size_t ) symbol.getRank ( ), 'S' ) );
+	}
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) {
+		res.addTransition ( 0, symbol, 0 );
+	}
+
+	unsigned i = 1;
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getContent ( ) ) {
+		res.addState ( i );
+		res.addTransition ( i - 1, symbol, i );
+		i++;
+	}
+
+	res.addFinalState ( i - 1 );
+	return res;
+}
+
+template < class SymbolType, class RankType >
+automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > ExactSubtreeMatchingAutomaton::construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & pattern ) {
+	automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > res ( 0, alphabet::BottomOfTheStackSymbol::instance < char > ( ) );
+
+	res.setPushdownStoreAlphabet ( { alphabet::BottomOfTheStackSymbol::instance < char > ( ), 'S' } );
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) {
+		res.addInputSymbol ( symbol );
+
+		if ( pattern.getBars ( ).count ( symbol ) )
+			res.setPushdownStoreOperation ( symbol, ext::vector < char > ( 1, 'S' ), ext::vector < char > { } );
+		else
+			res.setPushdownStoreOperation ( symbol, ext::vector < char > { }, ext::vector < char > ( 1, 'S' ) );
+	}
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) {
+		res.addTransition ( 0, symbol, 0 );
+	}
+
+	unsigned i = 1;
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getContent ( ) ) {
+		res.addState ( i );
+		res.addTransition ( i - 1, symbol, i );
+		i++;
+	}
+
+	res.addFinalState ( i - 1 );
+	return res;
+}
+
+template < class SymbolType, class RankType >
+unsigned constructRecursive ( const ext::tree < common::ranked_symbol < SymbolType, RankType > > & node, automaton::NFTA < SymbolType, RankType, unsigned > & res, unsigned & nextState ) {
+	ext::vector < unsigned > states;
+
+	states.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
+
+	for ( const ext::tree < common::ranked_symbol < SymbolType, RankType > > & child : node.getChildren ( ) )
+		states.push_back ( constructRecursive ( child, res, nextState ) );
+
+	unsigned state = nextState++;
+	res.addState ( state );
+	res.addTransition ( node.getData ( ), states, state );
+	return state;
+}
+
+template < class SymbolType, class RankType >
+automaton::NFTA < SymbolType, RankType, unsigned > ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTree < SymbolType, RankType > & pattern ) {
+	automaton::NFTA < SymbolType, RankType, unsigned > res;
+
+	res.setInputAlphabet ( pattern.getAlphabet ( ) );
+	unsigned nextState = 0;
+	res.addFinalState ( constructRecursive ( pattern.getContent ( ), res, nextState ) );
+	return res;
+}
+
 } /* namespace exact */
 
 } /* namespace arbology */