bzoj千题计划285:bzoj2555: SubString
http://www.lydsy.com/JudgeOnline/problem.php?id=2555
后缀自动机,用LCT维护parent树
一个串的出现次数 = parent 树 上 其所在状态 的 子树 叶节点 | Right | 之和
若在parent中np的子节点中加一个节点p,设p的 | Right | = sum,那么 根节点到np 的整条链上的所有状态的 | Right | 都要 + sum
若更换掉q原来的父节点, 设q的 | Right | = sum,那么 根节点到q 的整条链上的所有状态的 | Right | 都要 - sum
注意 decodeWithMask mask的修改 不影响全局的mask,全局的mask 只 会受 last_ans的影响
三个 无脑shabi错误的血泪史:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 600002 char s[3000001]; int tot=1,fa[N<<1],len[N<<1],ch[N<<1][26]; int p,q,np,nq,last=1; int mask; string chars; int sum[N<<1],tag[N<<1]; int Sfa[N<<1],Sch[N<<1][2]; int st[N<<1],top; void decodeWithMask(int mask) { scanf("%s",s); chars=s; int n=chars.length(); for (int j=0;j<n;j++) { mask=(mask*131+j)%n; char t=chars[j]; chars[j]=chars[mask]; chars[mask]=t; } } bool isroot(int x) { return Sch[Sfa[x]][0]!=x && Sch[Sfa[x]][1]!=x; } bool getson(int x) { return Sch[Sfa[x]][1]==x; } void tagging(int x,int y) { sum[x]+=y; tag[x]+=y; } void down(int x) { if(!tag[x]) return; if(Sch[x][0]) tagging(Sch[x][0],tag[x]); if(Sch[x][1]) tagging(Sch[x][1],tag[x]); tag[x]=0; } void rotate(int x) { int y=Sfa[x],z=Sfa[y]; int k=getson(x); if(!isroot(y)) Sch[z][Sch[z][1]==y]=x; Sch[y][k]=Sch[x][k^1]; Sch[x][k^1]=y; Sfa[x]=z; Sfa[y]=x; Sfa[Sch[y][k]]=y; } void splay(int x) { st[top=1]=x; for(int i=x;!isroot(i);i=Sfa[i]) st[++top]=Sfa[i]; for(int i=top;i;--i) down(st[i]); int y; while(!isroot(x)) { y=Sfa[x]; if(!isroot(y)) rotate(getson(y)==getson(x) ? y : x); rotate(x); } } void access(int x) { int t=0; while(x) { splay(x); Sch[x][1]=t; t=x; x=Sfa[x]; } } void link(int x,int f) { Sfa[x]=f; access(f); splay(f); tagging(f,sum[x]); } void cut(int x) { access(x); splay(x); tagging(Sch[x][0],-sum[x]); Sfa[Sch[x][0]]=0; Sch[x][0]=0; } void extend(int c) { len[np=++tot]=len[last]+1; sum[np]++; for(p=last;p && !ch[p][c]; p=fa[p]) ch[p][c]=np; if(!p) fa[np]=1,link(np,1); else { q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q,link(np,q); else { len[nq=++tot]=len[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[nq])); fa[nq]=fa[q]; link(nq,fa[q]); fa[q]=fa[np]=nq; cut(q); link(q,nq); link(np,nq); for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } last=np; } void build() { scanf("%s",s+1); int n=strlen(s+1); for(int i=1;i<=n;++i) extend(s[i]-'A'); } void add() { decodeWithMask(mask); int n=chars.length(); for(int i=0;i<n;++i) extend(chars[i]-'A'); } int query() { decodeWithMask(mask); int n=chars.length(); int now=1; for(int i=0;i<n;++i) if(!(now=ch[now][chars[i]-'A'])) return 0; splay(now); return sum[now]; } int main() { int T,ans; scanf("%d",&T); build(); while(T--) { scanf("%s",s); if(s[0]=='A') add(); else { ans=query(); printf("%d\n",ans); mask^=ans; } } }