Skip to content
Snippets Groups Projects
NormalizeRotation.h 1.94 KiB
Newer Older
#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 {
	 * 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 */
	size_t k = 0; /** Least circular string shift value */
	f [ 0 ] = -1;
Jan Trávníček's avatar
Jan Trávníček committed
	for ( size_t 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;
	}
	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 < SymbolType > { string.getAlphabet ( ), rotated };
} /* namespace simplify */

} /* namespace string */