【题目链接】
【前置技能】
- 后缀树
【题解】
- 要求支持向字符串后加一个字符,询问字符串中本质不同的子串的个数。
- 考虑建立原串的反串的后缀树,新出现的反串的后缀对于答案的贡献为 d e p [ p o s ] − d e p [ f a [ p o s ] ] dep[pos] - dep[fa[pos]] dep[pos]−dep[fa[pos]]。每次插入的时候维护一下答案即可。
【代码】
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define MAXN 100010
using namespace std;
int n;
LL ans;
template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
x = 0; int f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
struct Suffix_Automaton{
struct info{int fa, dep, tag; map <int, int> son;}a[MAXN * 2];
int cnt, root, last;
int create(int d){
++cnt;
a[cnt].dep = d;
return cnt;
}
void extend(int ch){
int p = last, np = create(a[p].dep + 1);
while (!a[p].son[ch]) {
a[p].son[ch] = np;
p = a[p].fa;
}
if (a[p].son[ch] == np) a[np].fa = root;
else {
int q = a[p].son[ch];
if (a[q].dep == a[p].dep + 1) a[np].fa = q;
else {
int nq = create(a[p].dep + 1);
a[nq].son = a[q].son;
a[nq].fa = a[q].fa;
a[q].fa = a[np].fa = nq;
while (a[p].son[ch] == q){
a[p].son[ch] = nq;
p = a[p].fa;
}
}
}
ans += a[np].dep - a[a[np].fa].dep;
last = np;
}
}SAM;
int main(){
read(n);
for (int i = 1; i <= n; ++i){
int t; read(t);
SAM.extend(t);
printf("%lld\n", ans);
}
return 0;
}