forked from indy256/codelibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
suffix_tree_ukkonen.cpp
70 lines (63 loc) · 1.52 KB
/
suffix_tree_ukkonen.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
using namespace std;
// See http://codeforces.ru/blog/entry/16780 for description
const int inf = 1e9;
const int maxn = 1e5;
char s[maxn];
unordered_map<char, int> to[maxn];
int len[maxn], f_pos[maxn], Link[maxn];
int node, pos;
int sz = 1, n = 0;
int make_node(int _pos, int _len) {
f_pos[sz] = _pos;
len[sz] = _len;
return sz++;
}
void go_edge() {
while (pos > len[to[node][s[n - pos]]]) {
node = to[node][s[n - pos]];
pos -= len[node];
}
}
void add_letter(char c) {
s[n++] = c;
pos++;
int last = 0;
while (pos > 0) {
go_edge();
int edge = s[n - pos];
int &v = to[node][edge];
int t = s[f_pos[v] + pos - 1];
if (v == 0) {
v = make_node(n - pos, inf);
Link[last] = node;
last = 0;
} else if (t == c) {
Link[last] = node;
return;
} else {
int u = make_node(f_pos[v], pos - 1);
to[u][c] = make_node(n - 1, inf);
to[u][t] = v;
f_pos[v] += pos - 1;
len[v] -= pos - 1;
v = u;
Link[last] = u;
last = u;
}
if (node == 0)
pos--;
else
node = Link[node];
}
}
int main() {
len[0] = inf;
string s = "abracadabra";
int ans = 0;
for (int i = 0; i < s.size(); i++)
add_letter(s[i]);
for (int i = 1; i < sz; i++)
ans += min((int)s.size() - f_pos[i], len[i]);
cout << ans << "\n";
}