Skip to content
Snippets Groups Projects
Commit dc979e7c authored by Jan Trávníček's avatar Jan Trávníček
Browse files

fix finding least lexicographical rotation

parent 7136b31e
No related branches found
No related tags found
No related merge requests found
...@@ -19,24 +19,23 @@ string::String NormalizeRotation::normalize(const string::String& string) { ...@@ -19,24 +19,23 @@ string::String NormalizeRotation::normalize(const string::String& string) {
   
string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString < >& string) { string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString < >& string) {
/** /**
* Lexicographically least circular substrings * Lexicographically least circular substrings,
* based on
* Kellogg S. Booth * Kellogg S. Booth
* 1979 * 1979,
* modified to working code by Ladislav Vagner
*/ */
const std::vector<alphabet::Symbol>& data = string.getContent(); 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 k = 0; /** Least circular string shift value */
int i;
f[0] = -1; f[0] = -1;
for (unsigned j = 1; j < 2 * data.size(); ++j) { for (unsigned j = 1; j < 2 * data.size(); ++j) {
/** condition adjusted by Radomir Polach, >= is not correct */ int i = f[j - k - 1];
if (j - k > data.size()) break; while ( i != -1 && data[j % data.size()] != data[(k + i + 1) % data.size()]) {
i = f[j - k - 1];
while (data[j % data.size()] != data[(k + i + 1) % data.size()] && i != -1) {
if (data[j % data.size()] < data[(k + i + 1) % data.size()]) k = j - i - 1; if (data[j % data.size()] < data[(k + i + 1) % data.size()]) k = j - i - 1;
i = f[i]; 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; if (data[j % data.size()] < data[(k + i + 1) % data.size()]) k = j;
f[j - k] = -1; f[j - k] = -1;
} else f[j - k] = i + 1; } else f[j - k] = i + 1;
...@@ -47,7 +46,7 @@ string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString ...@@ -47,7 +46,7 @@ string::CyclicString < > NormalizeRotation::normalize(const string::CyclicString
return string; return string;
   
std::vector<alphabet::Symbol> rotated; 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()]); rotated.push_back(data[l % data.size()]);
} }
   
......
...@@ -56,7 +56,7 @@ void compareTest::testCompareCyclic() { ...@@ -56,7 +56,7 @@ void compareTest::testCompareCyclic() {
string::CyclicString < > cyclic3n = string::simplify::NormalizeRotation::normalize(cyclic3); string::CyclicString < > cyclic3n = string::simplify::NormalizeRotation::normalize(cyclic3);
string::CyclicString < > cyclic4n = string::simplify::NormalizeRotation::normalize(cyclic4); string::CyclicString < > cyclic4n = string::simplify::NormalizeRotation::normalize(cyclic4);
   
CPPUNIT_ASSERT(cyclic1 == cyclic1n);
CPPUNIT_ASSERT(cyclic1n == cyclic2n); CPPUNIT_ASSERT(cyclic1n == cyclic2n);
CPPUNIT_ASSERT(cyclic1n == cyclic3n); CPPUNIT_ASSERT(cyclic1n == cyclic3n);
CPPUNIT_ASSERT(cyclic2n == cyclic3n); CPPUNIT_ASSERT(cyclic2n == cyclic3n);
...@@ -64,5 +64,10 @@ void compareTest::testCompareCyclic() { ...@@ -64,5 +64,10 @@ void compareTest::testCompareCyclic() {
CPPUNIT_ASSERT(cyclic4n != cyclic1n); CPPUNIT_ASSERT(cyclic4n != cyclic1n);
CPPUNIT_ASSERT(cyclic4n != cyclic2n); CPPUNIT_ASSERT(cyclic4n != cyclic2n);
CPPUNIT_ASSERT(cyclic4n != cyclic3n); 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);
} }
   
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment