【BZOJ2555】SubString
题面
http://darkbzoj.tk/problem/2555
题解
$LCT$ 维护子树权值和。
注意 $makeroot(x)$ 是真的 $makeroot$。(能看懂的人应该都看懂了)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define ri register int #define N 600050 using namespace std; int mask; int q; char s[N],s0[N]; char tmp[N]; int cnt[N<<1]; void trans(int mask) { int n=strlen(s); for (ri i=0;i<n;i++) { mask=(mask*131+i)%n; swap(s[i],s[mask]); } } struct LinkCutTree { int sum[N<<1],sumi[N<<1],ch[N<<1][2]; int fa[N<<1]; bool rev[N<<1]; int stk[N<<1],top; bool notroot(int x) { return ch[fa[x]][0]==x || ch[fa[x]][1]==x; } bool opt(int x) { return ch[fa[x]][1]==x; } void update(int x) { sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+sumi[x]+cnt[x]; } void pushr(int x) { if (!rev[x]) return; rev[x]=0; swap(ch[x][0],ch[x][1]); if (ch[x][0]) rev[ch[x][0]]^=1; if (ch[x][1]) rev[ch[x][1]]^=1; } void rotate(int x) { //printf("ROTATE %d\n",x); int y=fa[x],z=fa[y],s=opt(x),w=ch[x][1^s]; fa[x]=z; if (notroot(y)) ch[z][opt(y)]=x; if (w) fa[w]=y; ch[y][s]=w; ch[x][1^s]=y; fa[y]=x; update(y); update(x); } void splay(int x) { //printf("SPLAY %d\n",x); top=1; int y=x; while (notroot(y)) stk[top++]=y,y=fa[y]; stk[top]=y; while (top) pushr(stk[top]),top--; while (notroot(x)) { if (!notroot(fa[x])) rotate(x); else { if (opt(x)==opt(fa[x])) rotate(fa[x]); else rotate(x); rotate(x); } } } void access(int x) { //printf("ACCESS %d\n",x); int y=0; while (x) { splay(x); sumi[x]+=sum[ch[x][1]]; sumi[x]-=sum[ch[x][1]=y]; update(x); y=x; x=fa[x]; } } void makeroot(int x) { //printf("MAKEROOT %d\n",x); access(x); splay(x); rev[x]^=1; pushr(x); } void link(int x,int ff) { //printf("LINK %d %d\n",x,ff); makeroot(x); access(ff); splay(ff); fa[x]=ff; sumi[ff]+=sum[x]; update(ff); } void cut(int x,int ff) { //printf("CUT %d %d\n",x,ff); makeroot(ff); access(x); splay(x); ch[x][opt(ff)]=fa[ff]=0; update(x); } int query(int x) { if (!x) return 0; makeroot(1); access(x); return sum[x]-sum[ch[x][0]]-sum[ch[x][1]]; } } lct; struct SuffixAutoMachine { int len[N<<1],ff[N<<1]; int ch[N<<1][26]; int ton[N<<1],a[N<<1]; int aaa[N<<1]; int las,tot; inline void init() {tot=las=1;} inline void extend(int c) { int p=las,np=++tot; las=np; cnt[np]=1; len[np]=len[p]+1; while (p && !ch[p][c]) ch[p][c]=np,p=ff[p]; if (!p) ff[np]=1; else { int q=ch[p][c]; if (len[q]==len[p]+1) ff[np]=q; else { int nq=++tot; for (ri i=0;i<26;i++) ch[nq][i]=ch[q][i]; ff[nq]=ff[q]; len[nq]=len[p]+1; lct.link(nq,ff[nq]); lct.cut(q,ff[q]); ff[np]=ff[q]=nq; lct.link(q,ff[q]); while (p && ch[p][c]==q) ch[p][c]=nq,p=ff[p]; } } lct.link(np,ff[np]); } int find() { int now=1; for (ri i=0,l=strlen(s);i<l;i++) now=ch[now][s[i]-'A']; return now; } } sam; int main(){ scanf("%d",&q); scanf("%s",s); sam.init(); for (ri i=0,l=strlen(s);i<l;i++) sam.extend(s[i]-'A'); for (ri j=1;j<=q;j++) { scanf("%s",s0); if (s0[0]=='Q') { scanf("%s",s); trans(mask); int p=sam.find(); int ans2=lct.query(p); printf("%d\n",ans2); mask^=ans2; } else { scanf("%s",s); trans(mask); for (ri i=0,l=strlen(s);i<l;i++) sam.extend(s[i]-'A'); } } }