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; }