/*
 * ExactEqual.h
 *
 *  Created on: Oct 14, 2014
 *	  Author: Radomir Polach
 */

#ifndef EXACT_EQUAL_H_
#define EXACT_EQUAL_H_

#include <string/LinearString.h>
#include <string/CyclicString.h>

namespace string {

namespace naive {

/**
 * Implements exact equality test of string contents.
 *
 */
class ExactEqual {
public:
	/**
	 * Implements exact equality test of string contents.
	 *
	 * \tparam SymbolType the of symbols in the string
	 *
	 * \param u the first string to compare
	 * \param v the second string to compare
	 *
	 * \return true if strings are equal, false othervise
	 */
	template < class SymbolType >
	static bool equals(const string::LinearString < SymbolType >& u, const string::LinearString < SymbolType >& v);

	/**
	 * Implements exact equality test of string contens. The algorithm handles rotations of strings.
	 *
	 * \tparam SymbolType the of symbols in the string
	 *
	 * \param u the first string to compare
	 * \param v the second string to compare
	 *
	 * \return true if strings are equal in some rotation, false othervise
	 */
	template < class SymbolType >
	static bool equals(const string::CyclicString < SymbolType >& u, const string::CyclicString < SymbolType >& v);
};

template < class SymbolType >
bool ExactEqual::equals ( const string::LinearString < SymbolType > & u, const string::LinearString < SymbolType > & v ) {
	int n = ( int ) u.getContent ( ).size ( );
	int m = ( int ) v.getContent ( ).size ( );
	int k = 0;

	while ( k < n && k < m && u.getContent ( )[k] == v.getContent ( )[k] ) k++;

	if ( ( k == m ) && ( k == n ) )
		return true;
	else
		return false;
}

template < class SymbolType >
bool ExactEqual::equals ( const string::CyclicString < SymbolType > & u, const string::CyclicString < SymbolType > & v ) {
	int n = ( int ) u.getContent ( ).size ( );
	int i = -1;
	int j = -1;

	if ( n != ( int ) v.getContent ( ).size ( ) ) return false;

	while ( i < n - 1 && j < n - 1 ) {
		int k = 1;

		while ( k <= n && u.getContent ( )[( i + k ) % n] == v.getContent ( )[( j + k ) % n] ) k++;

		if ( k > n ) return true;

		if ( u.getContent ( )[( i + k ) % n] > v.getContent ( )[( j + k ) % n] )
			i += k;
		else
			j += k;
	}

	return false;
}

} /* namespace naive */

} /* namespace string */

#endif /* EXACT_EQUAL_H_ */
