BZOJ2555: SubString
这题写得我真想吐...
主要注意一个地方。
1.每次cut的时候,cut的一颗子树,而不是只有q这个节点。
说到底,还是没有对fail树的形态有一个清晰地认识,不过这道题写后就好很多。
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iomanip> #include<set> #include<map> #include<queue> using namespace std; #define mem1(i,j) memset(i,j,sizeof(i)) #define mem2(i,j) memcpy(i,j,sizeof(i)) #define LL long long #define up(i,j,n) for(int i=(j);i<=(n);i++) #define FILE "dealing" #define poi vec #define eps 1e-10 #define db double const int maxn=1620000,inf=1000000000,mod=1000000007; int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();} return f*x; } bool cmax(int& a,int b){return a<b?a=b,true:false;} bool cmin(int& a,int b){return a>b?a=b,true:false;} string s;char ch[maxn];int mask=0; namespace LCT{ int c[maxn][2],fa[maxn],val[maxn],siz[maxn],rev[maxn],delet[maxn]; bool isroot(int x){if(!x)return 1;return c[fa[x]][1]!=x&&c[fa[x]][0]!=x;} //void revv(int x){if(!x)return;swap(c[x][0],c[x][1]);rev[x]^=1;} void add(int x,int d){if(!x)return;delet[x]+=d;val[x]+=d;} void pushdown(int x){ if(!x)return; //if(rev[x]){rev[x]^=1;revv(c[x][1]);revv(c[x][0]);} if(delet[x])add(c[x][1],delet[x]),add(c[x][0],delet[x]),delet[x]=0; } void rotate(int x){ if(!x)return; int y=fa[x],z=fa[y],d=c[y][1]==x; if(!isroot(y))c[z][c[z][1]==y]=x; fa[y]=x;fa[x]=z;if(c[x][d^1])fa[c[x][d^1]]=y; c[y][d]=c[x][d^1];c[x][d^1]=y; } int q[maxn],top=0; void splay(int x){ q[++top]=x; for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i]; while(top)pushdown(q[top--]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if(c[y][1]==x^c[z][1]==y)rotate(x); else rotate(y); } rotate(x); } } void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t;} void cut(int x){ access(x);splay(x); add(c[x][0],-val[x]); c[x][0]=fa[c[x][0]]=0; } void link(int x,int y){ access(y);splay(y);fa[x]=y; add(y,val[x]); } }; namespace SAM{ int c[maxn][26],pre[maxn],len[maxn],cnt=1,now=1,Now=1; void extend(int x){ int nq,np,q,p; p=Now;Now=np=++cnt;len[np]=len[p]+1;LCT::val[np]++; while(p&&!c[p][x])c[p][x]=np,p=pre[p]; if(!p){pre[np]=1; LCT::link(np,1); } else { q=c[p][x]; if(len[q]==len[p]+1)pre[np]=q,LCT::link(np,q); else { len[nq=++cnt]=len[p]+1; mem2(c[nq],c[q]); pre[nq]=pre[q]; LCT::link(nq,pre[q]); LCT::cut(q); LCT::link(q,nq); LCT::link(np,nq); pre[q]=pre[np]=nq; while(p&&c[p][x]==q)c[p][x]=nq,p=pre[p]; } } } int Len=0; void prepare(){Len=0,now=1;} int walk(int x){ while(pre[now]&&!c[now][x])now=pre[now],Len=len[now]; if(!c[now][x])return 0; now=c[now][x];Len++;return Len; } int solve(){ LCT::access(now);LCT::splay(now);return LCT::val[now]; } void build(char* s){ int n=strlen(s+1);Now=1,cnt=1; up(i,1,n)extend(s[i]-'A'); } }; void load(int mask){ scanf("%s",ch); s=ch; up(j,0,s.length()-1){ mask=(mask*131+j)%s.length(); char t=s[j]; s[j]=s[mask]; s[mask]=t; } } int main(){ //freopen(FILE".in","r",stdin); //freopen(FILE".out","w",stdout); int Q=read(); scanf("%s",ch+1); SAM::build(ch); while(Q--){ scanf("%s",ch+1); if(ch[1]=='Q'){ load(mask); //cin>>s; SAM::prepare();int n=s.length(),m; up(i,0,n-1)m=SAM::walk(s[i]-'A'); int ans=(m==n?SAM::solve():0); mask^=ans; printf("%d\n",ans); } else { load(mask); //cin>>s; int n=s.length(); up(i,0,n-1)SAM::extend(s[i]-'A'); } } return 0; }