【后缀自动机】生成魔咒

传送门:LOJ2033


思路:似乎是后缀自动机裸题,每次把新字符加入后缀自动机,更新答案即可。

注意:由于字符集较大,转移要用map来储存。


代码如下:

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
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
#define N 300000
#define LL long long
int n,x,cnt,p,np,q,nq,stt[N],fa[N];
LL ans;
map<int,int> c[N];
void extend(int w){
p=np; stt[np=++cnt]=stt[p]+1;
for (;p && !c[p].count(w);p=fa[p]) c[p][w]=np;
if (!p) fa[np]=1;
else{
if (stt[q=c[p][w]]==stt[p]+1) fa[np]=q;
else{
stt[nq=++cnt]=stt[p]+1;
for (map<int,int>::iterator i=c[q].begin();i!=c[q].end();i++) c[nq][i->first]=i->second;
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
for (;p && c[p][w]==q;p=fa[p]) c[p][w]=nq;
}
}
}
int main(){
scanf("%d",&n); cnt=np=1;
for (int i=1;i<=n;i++){
scanf("%d",&x);
extend(x);
ans+=stt[np]-stt[fa[np]];
printf("%lld\n",ans);
}
}