summaryrefslogtreecommitdiff
path: root/string/suffixTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'string/suffixTree.cpp')
-rw-r--r--string/suffixTree.cpp151
1 files changed, 78 insertions, 73 deletions
diff --git a/string/suffixTree.cpp b/string/suffixTree.cpp
index fe065b2..f96992e 100644
--- a/string/suffixTree.cpp
+++ b/string/suffixTree.cpp
@@ -1,78 +1,83 @@
-// Baut Suffixbaum online auf. Laufzeit: O(n)
-// Einmal initSuffixTree() aufrufen und dann extend für jeden Buchstaben.
-// '\0'-Zeichen (oder ähnliches) an den Text anhängen!
-string s;
-int root, lastIdx, needsSuffix, pos, remainder, curVert, curEdge, curLen;
-struct Vert {
- int start, end, suffix; // Kante [start,end)
- map<char, int> next;
- int len() { return min(end, pos + 1) - start; }
-};
-vector<Vert> tree;
+struct SuffixTree {
+ struct Vert {
+ int start, end, suffix;
+ map<char, int> next;
+ };
+ string s;
+ int root, lastIdx, needsSuffix, pos, remainder;
+ int curVert, curEdge, curLen;
+ // Each Vertex gives its children range as [start, end)
+ vector<Vert> tree;
-int newVert(int start, int end) {
- Vert v;
- v.start = start;
- v.end = end;
- v.suffix = 0;
- tree.push_back(v);
- return ++lastIdx;
-}
+ SuffixTree(string& s) : s(s) {
+ needsSuffix = remainder = curEdge = curLen = 0;
+ lastIdx = pos = -1;
+ root = curVert = newVert(-1, -1);
+ for (int i = 0; i < sz(s); i++) extend();
+ }
-void addSuffixLink(int vert) {
- if (needsSuffix) tree[needsSuffix].suffix = vert;
- needsSuffix = vert;
-}
+ int newVert(int start, int end) {
+ Vert v;
+ v.start = start;
+ v.end = end;
+ v.suffix = 0;
+ tree.push_back(v);
+ return ++lastIdx;
+ }
-bool fullImplicitEdge(int vert) {
- if (curLen >= tree[vert].len()) {
- curEdge += tree[vert].len();
- curLen -= tree[vert].len();
- curVert = vert;
- return true;
- }
- return false;
-}
+ int len(Vert& v) {
+ return min(v.end, pos + 1) - v.start;
+ }
-void initSuffixTree() {
- needsSuffix = remainder = curEdge = curLen = 0;
- lastIdx = pos = -1;
- root = curVert = newVert(-1, -1);
-}
+ void addSuffixLink(int vert) {
+ if (needsSuffix) tree[needsSuffix].suffix = vert;
+ needsSuffix = vert;
+ }
-void extend() {
- pos++;
- needsSuffix = 0;
- remainder++;
- while (remainder) {
- if (curLen == 0) curEdge = pos;
- if (!tree[curVert].next.count(s[curEdge])) {
- int leaf = newVert(pos, s.size());
- tree[curVert].next[s[curEdge]] = leaf;
- tree[curVert].next[s[curEdge]] = leaf;
- addSuffixLink(curVert);
- } else {
- int nxt = tree[curVert].next[s[curEdge]];
- if (fullImplicitEdge(nxt)) continue;
- if (s[tree[nxt].start + curLen] == s[pos]) {
- curLen++;
- addSuffixLink(curVert);
- break;
- }
- int split = newVert(tree[nxt].start, tree[nxt].start + curLen);
- tree[curVert].next[s[curEdge]] = split;
- int leaf = newVert(pos, s.size());
- tree[split].next[s[pos]] = leaf;
- tree[nxt].start += curLen;
- tree[split].next[s[tree[nxt].start]] = nxt;
- addSuffixLink(split);
- }
- remainder--;
- if (curVert == root && curLen) {
- curLen--;
- curEdge = pos - remainder + 1;
- } else {
- curVert = tree[curVert].suffix ? tree[curVert].suffix : root;
- }
- }
-}
+ bool fullImplicitEdge(int vert) {
+ if (curLen >= len(tree[vert])) {
+ curEdge += len(tree[vert]);
+ curLen -= len(tree[vert]);
+ curVert = vert;
+ return true;
+ }
+ return false;
+ }
+
+ void extend() {
+ pos++;
+ needsSuffix = 0;
+ remainder++;
+ while (remainder) {
+ if (curLen == 0) curEdge = pos;
+ if (!tree[curVert].next.count(s[curEdge])) {
+ int leaf = newVert(pos, sz(s));
+ tree[curVert].next[s[curEdge]] = leaf;
+ tree[curVert].next[s[curEdge]] = leaf;
+ addSuffixLink(curVert);
+ } else {
+ int nxt = tree[curVert].next[s[curEdge]];
+ if (fullImplicitEdge(nxt)) continue;
+ if (s[tree[nxt].start + curLen] == s[pos]) {
+ curLen++;
+ addSuffixLink(curVert);
+ break;
+ }
+ int split = newVert(tree[nxt].start,
+ tree[nxt].start + curLen);
+ tree[curVert].next[s[curEdge]] = split;
+ int leaf = newVert(pos, sz(s));
+ tree[split].next[s[pos]] = leaf;
+ tree[nxt].start += curLen;
+ tree[split].next[s[tree[nxt].start]] = nxt;
+ addSuffixLink(split);
+ }
+ remainder--;
+ if (curVert == root && curLen) {
+ curLen--;
+ curEdge = pos - remainder + 1;
+ } else {
+ curVert = tree[curVert].suffix ? tree[curVert].suffix
+ : root;
+ }}}
+}; \ No newline at end of file