SDOI 2016 生成魔咒

题目大意:一个字符串,刚开始为空,依次在后面添加一个字符,问每次添加完字符后本质不同的字符串有多少种

后缀自动机裸题,添加字符时,更新的结点个数即为新增加的子串

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int s=0;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';
    return s;
}
struct sam{
    int cnt,last;
    int fa[200010],l[200010];
    map<int,int>a[200010];
    long long ans;
    sam(){
        last=++cnt;
    }
    void add(int c){
        int p=last,np=last=++cnt;l[np]=l[p]+1;
        while(p&&!a[p][c])a[p][c]=np,p=fa[p];
        if(!p)fa[np]=1;
        else{
            int q=a[p][c];
            if(l[q]==l[p]+1)fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                a[nq]=a[q];
                fa[nq]=fa[q];
                fa[np]=fa[q]=nq;
                while(a[p][c]==q)a[p][c]=nq,p=fa[p];
            }
        }
        ans+=l[last]-l[fa[last]];
        printf("%lld\n",ans);
    }
}sam;
int main(){
    freopen("menci_incantation.in","r",stdin);
    freopen("menci_incantation.out","w",stdout);
    int n=read();
    for(int i=1;i<=n;++i){
        int x=read();sam.add(x);
    }return 0;
}
View Code

 

posted @ 2016-04-11 20:22  117208  阅读(342)  评论(0编辑  收藏  举报