BZOJ 5084: hashit 后缀自动机(原理题)
比较考验对后缀自动机构建过程的理解.
之前看题解写的都是树链的并,但是想了想好像可以直接撤销,复杂度是线性的.
自己想出来的,感觉后缀自动机的题应该不太能难倒我~
注意:一定要手画一下后缀自动机的构建过程,然后看着自己画的图一步一步模拟即可.
Code:
#include <stack> #include <cstdio> #include <cstring> #include <algorithm> #define N 200003 #define ll long long #define setIO(s) freopen(s".in","r",stdin) // ,freopen(s".out","w",stdout) using namespace std; struct Node { int node,i,p,fanq,q; Node(int node=0,int i=0,int p=0,int fanq=0,int q=0):node(node),i(i),p(p),fanq(fanq),q(q){} }; ll now; char S[N]; stack<Node>sta; int ch[N][26],f[N],len[N],pre[N],tot,n,C[N]; int extend(int lst,int c) { int np=++tot,p=lst; len[np]=len[p]+1; for(;p&&!ch[p][c];p=f[p]) ch[p][c]=np; if(!p) f[np]=1; else { int q=ch[p][c]; if(len[q]==len[p]+1) f[np]=q; else { int nq=++tot; len[nq]=len[p]+1, f[nq]=f[q], f[np]=f[q]=nq; sta.push(Node(nq,np,p,f[nq],q)); memcpy(ch[nq],ch[q],sizeof(ch[q])); for(;p&&ch[p][c]==q;p=f[p]) ch[p][c]=nq; } } now+=(ll)len[np]-len[f[np]]; sta.push(Node(np,np,lst,0,0)); return np; } int main() { int i,j,cur; scanf("%s",S+1),n=strlen(S+1); cur=pre[1]=tot=1; for(i=1;i<=n;++i) { if(S[i]=='-') { while(!sta.empty() && sta.top().i==cur) { Node e=sta.top(); sta.pop(); if(e.fanq) { int p=e.p,fanq=e.fanq,nq=e.node,q=e.q,c=C[e.i]; for(;p&&ch[p][c]==nq;p=f[p]) ch[p][c]=q; f[q]=f[nq]; } else { int np=e.node,p=e.p,c=C[e.i]; now-=(len[np]-len[f[np]]); for(;p&&ch[p][c]==np;p=f[p]) ch[p][c]=0; } } cur=pre[cur]; } else { int x=cur; cur=extend(x,S[i]-'a'), pre[cur]=x, C[cur]=S[i]-'a'; } printf("%lld\n",now); } return 0; }