From efa5497c85bc46709d1e357570332fc474d6456d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ing=2E=20Radom=C3=ADr=20Pol=C3=A1ch?= <polacrad@fit.cvut.cz> Date: Sun, 14 Sep 2014 14:27:36 +0200 Subject: [PATCH] FEATURE: cyclic string canonical form in O(n) time and O(n) space --- alib2data/makefile | 2 +- alib2data/src/string/CyclicString.cpp | 41 ++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/alib2data/makefile b/alib2data/makefile index 57af86af63..f138e3cb54 100644 --- a/alib2data/makefile +++ b/alib2data/makefile @@ -2,7 +2,7 @@ SHELL:=/bin/bash LIBRARY:=libalib2data.so TESTBIN:=alib2test -LDFLAGS:= /usr/lib64/libbfd.a /usr/lib64/libiberty.a -lz -ldl -rdynamic -shared -lxml2 +LDFLAGS:=-lbfd -liberty -lz -ldl -rdynamic -shared -lxml2 TEST_LDFLAGS:= -L../alib2data/lib -rdynamic -lxml2 -lalib2data -lcppunit -Wl,-rpath,. OBJECTS:=$(patsubst src/%.cpp, obj/%.o, $(shell find src/ -name *cpp)) diff --git a/alib2data/src/string/CyclicString.cpp b/alib2data/src/string/CyclicString.cpp index dccd4fad7f..fcf1fc8e58 100644 --- a/alib2data/src/string/CyclicString.cpp +++ b/alib2data/src/string/CyclicString.cpp @@ -83,13 +83,40 @@ void CyclicString::setContent(std::vector<alphabet::Symbol> data) { if(unknownSymbols.size() > 0) throw exception::AlibException("Input symbols not in the alphabet."); - m_Data = data; - for(unsigned i = 1; i < data.size(); i++) { - data.push_back(std::move(data[0])); - data.erase(data.begin()); - - if(m_Data > data) m_Data = data; - } + /** + * Lexicographically least circular substrings + * Kellogg S. Booth + * 1979 + */ + int* f = new int[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 RadomĂr Polách, >= 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) { + 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 (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) { + m_Data = data; + return; + } + + std::vector<alphabet::Symbol> tmp; + for (unsigned l = k; l < data.size() + k; ++l) { + tmp.push_back(std::move(data[l % data.size()])); + } + m_Data = tmp; } bool CyclicString::isEmpty() const { -- GitLab