bzoj4516 / P4070 [SDOI2016]生成魔咒

P4070 [SDOI2016]生成魔咒

后缀自动机

每插入一个字符,对答案的贡献为$len[last]-len[fa[last]]$

插入字符范围过大,所以使用$map$存储。

(去掉第35行就是裸的板子了。)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cctype>
 5 #include<map>
 6 using namespace std;
 7 void read(int &x){
 8     static char c=getchar();x=0;
 9     while(!isdigit(c)) c=getchar();
10     while(isdigit(c)) x=x*10+(c^48),c=getchar();
11 }
12 #define N 100005
13 long long ans;
14 struct Sam{
15     int fa[N<<1],len[N<<1];
16     int last,ed,p,q;
17     map <int,int> nxt[N<<1];
18     Sam(){last=ed=1;}
19     void init(){
20         int n,c; read(n);
21         while(n--) read(c),add(c),printf("%lld\n",ans);
22     }
23     void add(int c){
24         p=last; len[last=++ed]=len[p]+1;
25         for(;p&&!nxt[p][c];p=fa[p]) nxt[p][c]=ed;
26         if(!p) fa[ed]=1;
27         else{
28             q=nxt[p][c];
29             if(len[q]==len[p]+1) fa[ed]=q;
30             else{
31                 len[++ed]=len[p]+1; nxt[ed]=nxt[q];
32                 fa[ed]=fa[q]; fa[q]=fa[ed-1]=ed;
33                 for(;nxt[p][c]==q;p=fa[p]) nxt[p][c]=ed;
34             }
35         }ans+=len[last]-len[fa[last]];//对答案的贡献
36     }
37 }sam;
38 int main(){sam.init(); return 0;}

 

posted @ 2019-01-04 16:44  kafuuchino  阅读(150)  评论(0编辑  收藏  举报