From dc979e7c5a0b9393165de47da8564a8c2d208eb6 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 21 Dec 2016 20:13:41 +0100
Subject: [PATCH] fix finding least lexicographical rotation

---
 .../src/string/simplify/NormalizeRotation.cpp | 19 +++++++++----------
 .../test-src/string/compare/compareTest.cpp   |  7 ++++++-
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/alib2algo/src/string/simplify/NormalizeRotation.cpp b/alib2algo/src/string/simplify/NormalizeRotation.cpp
index a2d3adc831..b8b9c35043 100644
--- a/alib2algo/src/string/simplify/NormalizeRotation.cpp
+++ b/alib2algo/src/string/simplify/NormalizeRotation.cpp
@@ -19,24 +19,23 @@ string::String NormalizeRotation::normalize(const string::String& string) {
 
 string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString < >& string) {
 	/**
-	 * Lexicographically least circular substrings
+	 * Lexicographically least circular substrings,
+	 * based on
 	 * Kellogg S. Booth
-	 * 1979
+	 * 1979,
+	 * modified to working code by Ladislav Vagner
 	 */
 	const std::vector<alphabet::Symbol>& data = string.getContent();
-	int* f = new int[data.size() + 1]; /** Knuth–Morris–Pratt like array */
+	int* f = new int[ 2 * data.size() ]; /** Knuth–Morris–Pratt like array */
 	int k = 0; /** Least circular string shift value */
-	int i;
 	f[0] = -1;
 	for (unsigned j = 1; j < 2 * data.size(); ++j) {
-		/** condition adjusted by Radomir Polach, >= is not correct */
-		if (j - k > data.size()) break; 
-		i = f[j - k - 1];
-		while (data[j % data.size()] != data[(k + i + 1) % data.size()] && i != -1) {
+		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 (data[j % data.size()] != data[(k + i + 1) % data.size()] && i == -1) {
+		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;
@@ -47,7 +46,7 @@ string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString
 		return string;
 
 	std::vector<alphabet::Symbol> rotated;
-	for (unsigned l = k; l < data.size() + k; ++l) {
+	for (unsigned l = k % data.size ( ); l < data.size() + k % data.size ( ); ++l) {
 		rotated.push_back(data[l % data.size()]);
 	}
 
diff --git a/alib2algo/test-src/string/compare/compareTest.cpp b/alib2algo/test-src/string/compare/compareTest.cpp
index 2606492375..b380ec5a43 100644
--- a/alib2algo/test-src/string/compare/compareTest.cpp
+++ b/alib2algo/test-src/string/compare/compareTest.cpp
@@ -56,7 +56,7 @@ void compareTest::testCompareCyclic() {
 	string::CyclicString < > cyclic3n = string::simplify::NormalizeRotation::normalize(cyclic3);
 	string::CyclicString < > cyclic4n = string::simplify::NormalizeRotation::normalize(cyclic4);
 
-
+	CPPUNIT_ASSERT(cyclic1  == cyclic1n);
 	CPPUNIT_ASSERT(cyclic1n == cyclic2n);
 	CPPUNIT_ASSERT(cyclic1n == cyclic3n);
 	CPPUNIT_ASSERT(cyclic2n == cyclic3n);
@@ -64,5 +64,10 @@ void compareTest::testCompareCyclic() {
 	CPPUNIT_ASSERT(cyclic4n != cyclic1n);
 	CPPUNIT_ASSERT(cyclic4n != cyclic2n);
 	CPPUNIT_ASSERT(cyclic4n != cyclic3n);
+
+	string::CyclicString < > cyclic5({alphabet::Symbol(62), alphabet::Symbol(62), alphabet::Symbol(100), alphabet::Symbol(62)});
+	string::CyclicString < > cyclic5n = string::simplify::NormalizeRotation::normalize(cyclic5);
+	string::CyclicString < > cyclic5r({alphabet::Symbol(62), alphabet::Symbol(62), alphabet::Symbol(62), alphabet::Symbol(100)});
+	CPPUNIT_ASSERT(cyclic5n == cyclic5r);
 }
 
-- 
GitLab