考虑在extend($x$)的时候维护SAM中所有串出现的次数,存在每个节点上
在$S$的尾部加入一个字符$x$,只有($S$的后缀+$x$)这种串会多出现一次,所以extend完之后把$np$在parent树中的所有祖先答案$+1$
在extend的过程中只有常数次切换$parent$,相应维护即可
我们要维护parent树,支持link,cut,链增值,点查询,写个lct就好了
糟心...xsy上就是过不了
#include<stdio.h> #include<string.h> #define N 1200010 struct lct{ int fa[N],ch[N][2],v[N],d[N],stk[N]; #define ls ch[x][0] #define rs ch[x][1] void ad(int x,int f){ v[x]+=f; d[x]+=f; } void pushdown(int x){ if(d[x]){ if(ls)ad(ls,d[x]); if(rs)ad(rs,d[x]); d[x]=0; } } void rot(int x){ int y,z,f,b; y=fa[x]; z=fa[y]; f=(ch[y][0]==x); b=ch[x][f]; fa[x]=z; fa[y]=x; if(b)fa[b]=y; ch[x][f]=y; ch[y][f^1]=b; if(ch[z][0]==y)ch[z][0]=x; if(ch[z][1]==y)ch[z][1]=x; } bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} void gao(int x){ int t=0; while(!isrt(x)){ t++; stk[t]=x; x=fa[x]; } t++; stk[t]=x; for(;t;t--)pushdown(stk[t]); } void splay(int x){ int y,z; gao(x); while(!isrt(x)){ y=fa[x]; z=fa[y]; if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x); rot(x); } } void access(int x){ int y=0; while(x){ splay(x); rs=y; y=x; x=fa[x]; } } void add(int y,int f){ access(y); splay(y); ad(y,f); } void link(int x,int y){ if(x==0||y==0)return; fa[x]=y; add(y,v[x]); } void cut(int x){ access(x); splay(x); ad(ls,-v[x]); fa[ls]=0; ls=0; } }l; struct sam{ int ch[26],fa,v; }t[N]; int M=1,las=1; void extend(int c){ int p=las,np=++M,q,nq; t[np].v=t[p].v+1; while(p&&t[p].ch[c]==0){ t[p].ch[c]=np; p=t[p].fa; } if(p==0){ t[np].fa=1; l.link(np,1); }else{ q=t[p].ch[c]; if(t[q].v==t[p].v+1){ t[np].fa=q; l.link(np,q); }else{ nq=++M; t[nq]=t[q]; l.link(nq,t[q].fa); t[nq].v=t[p].v+1; l.cut(q); t[np].fa=t[q].fa=nq; l.link(q,nq); l.link(np,nq); while(p&&t[p].ch[c]==q){ t[p].ch[c]=nq; p=t[p].fa; } } } las=np; l.add(np,1); } char s[N]; void decode(int mask){ int i,n; char c; n=strlen(s); for(i=0;i<n;i++){ mask=(mask*131+i)%n; c=s[i]; s[i]=s[mask]; s[mask]=c; } } void insert(){ for(int i=0;s[i];i++)extend(s[i]-‘A‘); } int query(){ int i,p; for(i=0,p=1;s[i];i++){ s[i]-=‘A‘; if(t[p].ch[s[i]]==0)return 0; p=t[p].ch[s[i]]; } l.gao(p); return l.v[p]; } int main(){ int m,res,mask=0; char ch[10]; scanf("%d%s",&m,s); insert(); while(m--){ scanf("%s%s",ch,s); decode(mask); if(ch[0]==‘A‘) insert(); else{ res=query(); printf("%d\n",res); mask^=res; } } }