/* * NormalizeRotation.h * * Created on: 9. 2. 2014 * Author: Jan Travnicek */ #ifndef _NORMALIZE_ROTATION_H__ #define _NORMALIZE_ROTATION_H__ #include <string/CyclicString.h> namespace string { namespace simplify { /** * Computes lexicographically least circular rotation, * based on Kellogg S. Booth 1979, * modified to working code by Ladislav Vagner */ class NormalizeRotation { public: /** * Computes lexicographically least circular rotation, * based on Kellogg S. Booth 1979, * modified to working code by Ladislav Vagner * * \tparam SymbolType the type of symbols in the rotated string. * * \param string the rotated string * * \return the @p string in its least lexicographical rotation */ template < class SymbolType > static string::CyclicString < SymbolType > normalize(const string::CyclicString < SymbolType > & string); }; template < class SymbolType > string::CyclicString < SymbolType > NormalizeRotation::normalize(const string::CyclicString < SymbolType > & string) { const ext::vector < SymbolType > & data = string.getContent ( ); int * f = new int [ 2 * data.size ( ) ]; /** Knuth–Morris–Pratt like array */ int k = 0; /** Least circular string shift value */ f [ 0 ] = -1; for ( unsigned j = 1; j < 2 * data.size ( ); ++j ) { int i = f [ j - k - 1 ]; while ( i != -1 && data [ j % data.size ( ) ] != data [ ( k + i + 1 ) % data.size ( ) ] ) { if ( data [ j % data.size ( ) ] < data [ ( k + i + 1 ) % data.size ( ) ] ) k = j - i - 1; i = f [ i ]; } if ( i == -1 && data [ j % data.size ( ) ] != data [ k % data.size ( ) ] ) { if ( data [ j % data.size ( ) ] < data [ ( k + i + 1 ) % data.size ( ) ] ) k = j; f [ j - k ] = -1; } else f [ j - k ] = i + 1; } delete [] f; if(k == 0) return string; ext::vector < SymbolType > rotated; for ( unsigned l = k % data.size ( ); l < data.size() + k % data.size ( ); ++l ) { rotated.push_back ( data [ l % data.size ( ) ] ); } return string::CyclicString < > { string.getAlphabet ( ), rotated }; } } /* namespace simplify */ } /* namespace string */ #endif /* _NORMALIZE_ROTATION_H__ */