题解:用LCT维护parent树的Right集合大小
为什么我的代码这么慢???
问题:对SAM理解的还不够深
吐槽:神加密
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=1200009; int T; int fa[maxn],ch[maxn][2],tag[maxn],v[maxn],rev[maxn]; inline int son(int x){ if(ch[fa[x]][1]==x)return 1; else return 0; } inline bool isroot(int x){ return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x); } inline void pushup(int x){ } inline void pushdown(int x){ if(tag[x]){ tag[ch[x][0]]+=tag[x]; tag[ch[x][1]]+=tag[x]; v[ch[x][0]]+=tag[x]; v[ch[x][1]]+=tag[x]; tag[x]=0; } if(rev[x]){ rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]^=1; swap(ch[x][0],ch[x][1]); } } void Downfa(int x){ if(!isroot(x))Downfa(fa[x]); pushdown(x); } inline void Rotate(int x){ int y=fa[x]; int z=fa[y]; int b=son(x),c=son(y); int a=ch[x][b^1]; if(!isroot(y))ch[z][c]=x; fa[x]=z; if(a)fa[a]=y; ch[y][b]=a; fa[y]=x;ch[x][b^1]=y; pushup(y);pushup(x); } void Splay(int x){ Downfa(x); while(!isroot(x)){ int y=fa[x]; if(isroot(y)){ Rotate(x); }else{ if(son(x)==son(y)){ Rotate(y);Rotate(x); }else{ Rotate(x);Rotate(x); } } } } void Access(int x){ for(int t=0;x;t=x,x=fa[x]){ Splay(x);ch[x][1]=t;pushup(x); } } void Makeroot(int x){ Access(x);Splay(x);rev[x]^=1; } void Linkp(int x,int y){ Makeroot(x);fa[x]=y; } void Cutp(int x,int y){ Makeroot(x);Access(y);Splay(y); fa[ch[y][0]]=0;ch[y][0]=0;pushup(y); } void Addpath(int x,int y){ Makeroot(x);Access(y);Splay(y); tag[y]+=1;v[y]+=1; } int SAMsiz,last,cur; int ch2[maxn][27]; int dis[maxn]; int par[maxn]; void BuildSAM(int c,int idp){ cur=++SAMsiz; dis[cur]=idp; int p=last;last=cur; for(;p&&!ch2[p][c];p=par[p])ch2[p][c]=cur; if(!p){ par[cur]=1; Linkp(cur,1); Addpath(1,cur); }else{ int q=ch2[p][c]; if(dis[q]==dis[p]+1){ par[cur]=q; Linkp(cur,q); Addpath(1,cur); }else{ int nt=++SAMsiz; memcpy(ch2[nt],ch2[q],sizeof(ch2[nt])); dis[nt]=dis[p]+1; Cutp(q,par[q]); Linkp(q,nt); Linkp(nt,par[q]); Linkp(cur,nt); Splay(q);Splay(nt); v[nt]=v[q]; Addpath(1,cur); par[nt]=par[q]; par[q]=par[cur]=nt; for(;ch2[p][c]==q;p=par[p])ch2[p][c]=nt; } } } int mask,m,nowlen; char opty[maxn]; char opts[maxn]; void Decode(){ // return; int t=mask; for(int i=0;i<m;++i){ t=(t*131+i)%m; swap(opts[i],opts[t]); } } void Addstring(){ for(int i=0;i<m;++i)BuildSAM(opts[i]-‘A‘,nowlen+i+1); nowlen+=m; } int Getans(){ int x=1; for(int i=0;i<m;++i){ int c=opts[i]-‘A‘; x=ch2[x][c]; } if(!x)return 0; Splay(x); return v[x]; } int main(){ scanf("%d",&T); SAMsiz=last=1; scanf("%s",opts); nowlen=m=strlen(opts); for(int i=0;i<m;++i)BuildSAM(opts[i]-‘A‘,i+1); while(T--){ scanf("%s%s",opty,opts); m=strlen(opts); Decode(); if(opty[0]==‘A‘){ Addstring(); }else{ int ans=Getans(); printf("%d\n",ans); mask^=ans; } } return 0; }