bzoj 2555 substring Posted on 2019-05-04 | Views: $SAM+LCT$ . 如果没有修改,就直接建出 $SAM$ ,询问时从根出发走到对应状态,该状态的 $siz$ 即为答案. 现在要支持修改,沿用上面思路,只不过要动态维护 $parent$ 树的形态,需要加边,删边. 套一个 $LCT$ 进行维护就可以了. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191#include<bits/stdc++.h>using namespace std;#define ll long longinline ll read(){ ll out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int Siz=26,MAXN=2e6+10;int lst=1,idx=1;int siz[MAXN],tag[MAXN];int stk[MAXN],tp=0;struct Link_Cut_Tree{ struct node { int ch[2],fa; node(){ch[0]=ch[1]=fa=0;} }Tree[MAXN];#define root Tree[x] bool isroot(int x) { return Tree[root.fa].ch[0]!=x && Tree[root.fa].ch[1]!=x; } void modifiy(int x,int c) { if(x) { siz[x]+=c; tag[x]+=c; } } void pushdown(int x) { if(tag[x]) { modifiy(root.ch[0],tag[x]); modifiy(root.ch[1],tag[x]); tag[x]=0; } } void rotate(int x) { int y=Tree[x].fa; int z=Tree[y].fa; if(!isroot(y)) Tree[z].ch[Tree[z].ch[1]==y]=x; Tree[x].fa=z; int k=(x==Tree[y].ch[1]); Tree[y].ch[k]=Tree[x].ch[k^1]; Tree[Tree[x].ch[k^1]].fa=y; Tree[x].ch[k^1]=y; Tree[y].fa=x; } void splay(int x) { stk[++tp]=x; for(int pos=x;!isroot(pos);pos=Tree[pos].fa) stk[++tp]=Tree[pos].fa; while(tp) pushdown(stk[tp--]); while(!isroot(x)) { int y=Tree[x].fa; int z=Tree[y].fa; if(!isroot(y)) (Tree[z].ch[0]==y)^(Tree[y].ch[0]==x)?rotate(x):rotate(y); rotate(x); } } void Access(int x) { for(int y=0;x;y=x,x=Tree[x].fa) { splay(x); Tree[x].ch[1]=y; } } void link(int x,int y) { Tree[x].fa=y; Access(y); splay(y); modifiy(y,siz[x]); } void cut(int x) { Access(x); splay(x); modifiy(Tree[x].ch[0],-siz[x]); Tree[x].ch[0]=Tree[Tree[x].ch[0]].fa=0; }}LCT;struct SuffixAutoMation{ int ch[MAXN][Siz],fa[MAXN]; int len[MAXN]; void Extend(int c) { int p=lst,np=++idx; lst=np; siz[np]=1; len[np]=len[p]+1; while(p && ch[p][c]==0) ch[p][c]=np,p=fa[p]; if(p==0) { fa[np]=1; LCT.link(np,1); } else { int q=ch[p][c]; if(len[q]==len[p]+1) { fa[np]=q; LCT.link(np,q); } else { int nq=++idx; len[nq]=len[p]+1; LCT.link(nq,fa[q]); LCT.cut(q); LCT.link(q,nq); LCT.link(np,nq); fa[nq]=fa[q]; fa[q]=fa[np]=nq; memcpy(ch[nq],ch[q],sizeof ch[q]); while(p && ch[p][c]==q) ch[p][c]=nq,p=fa[p]; } } }}SAM;int L;char buf[MAXN];void getinfo(int mask){ scanf("%s",buf); L=strlen(buf); for(int i=0; i<L; ++i) { mask=(mask*131+i) % L; swap(buf[i],buf[mask]); }}int mask=0;int main(){ int Q=read(); scanf("%s",buf); L=strlen(buf); for(int i=0;i<L;++i) SAM.Extend(buf[i]-'A'); while(Q--) { scanf("%s",buf); if(buf[0]=='A') //Add { getinfo(mask); for(int i=0;i<L;++i) SAM.Extend(buf[i]-'A'); } else //Query { getinfo(mask); int p=1; for(int i=0;i<L;++i) { p=SAM.ch[p][buf[i]-'A']; } if(!p) puts("0"); else { LCT.splay(p); printf("%d\n",siz[p]); mask^=siz[p]; } } } return 0;}