const int maxn = 100005;
struct Sam {
int next[maxn << 1][26];
int link[maxn << 1], step[maxn << 1];
int a[maxn], b[maxn << 1];
int sz, last, root;
void init() {
//如多次建立自动机,加入memset操作
root = sz = last = 1;
memset(next[root],0,sizeof(next[root]));
}
void add(int c) {
int p = last;
int np = ++sz;
last = np;
memset(next[np],0,sizeof(next[np]));
step[np] = step[p] + 1;
while(!next[p][c] && p) {
next[p][c] = np;
p = link[p];
}
if(p == 0) {
link[np] = root;
} else {
int q = next[p][c];
if(step[p] + 1 == step[q]) {
link[np] = q;
} else {
int nq = ++sz;
memcpy(next[nq], next[q], sizeof(next[q]));
step[nq] = step[p] + 1;
link[nq] = link[q];
link[q] = link[np] = nq;
while(next[p][c] == q && p) {
next[p][c] = nq;
p = link[p];
}
}
}
}
void build() {
init();
for(int i = 0; s[i]; i++) {
add(s[i] - 'a');
}
for(int i = 1; i <= sz; i++) {
a[step[i]]++;
}
for(int i = 1; i <= step[last]; i++) {
a[i] += a[i - 1];
}
for(int i = 1; i <= sz; i++) {
b[a[step[i]]--] = i;
}
}
} sam;
广义:
if(next[last][c] && step[last] + 1 == step[next[last][c]]) {
last = next[last][c];
return;
}
*需要边匹配边计算贡献的时候,父亲的贡献直接算,当前点的贡献要用匹配长度来算
*如果一个串需要多次在sam上跑,可以先全部跑完预处理出匹配信息,或者直接建进广义sam