BZOJ2555 SubString(后缀自动机+LCT)
询问串放在SAM上不跳fail跑到的节点的|right|即为答案。用LCT维护parent树即可。可以直接维护子树信息,也可以转化为路径加。注意强制在线所使用的mask是作为参数传进去的。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 1300010 #define lson tree[k].ch[0] #define rson tree[k].ch[1] #define lself tree[tree[k].fa].ch[0] #define rself tree[tree[k].fa].ch[1] char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int Q,n,m,cnt=1,last=1,son[N][26],fail[N],len[N],mask; char s[N],t[N]; struct data{int ch[2],fa,rev,s,sv,x; }tree[N]; void up(int k){tree[k].s=tree[k].sv+tree[lson].s+tree[rson].s+tree[k].x;} void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;} void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;} int whichson(int k){return rself==k;} bool isroot(int k){return lself!=k&&rself!=k;} void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);} void move(int k) { int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k); if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf; tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa; tree[k].ch[!p]=fa,tree[fa].fa=k; up(fa),up(k); } void splay(int k) { push(k); while (!isroot(k)) { int fa=tree[k].fa; if (!isroot(fa)) if (whichson(fa)^whichson(k)) move(k); else move(fa); move(k); } } void access(int k) { for (int t=0;k;t=k,k=tree[k].fa) { splay(k); tree[k].sv+=tree[rson].s-tree[t].s; rson=t; up(k); } } void makeroot(int k){access(k),splay(k),rev(k);} void link(int x,int y){makeroot(x);access(y),splay(y);tree[x].fa=y;tree[y].sv+=tree[x].s;up(y);} void cut(int x,int y){makeroot(x),access(y),splay(y);tree[y].ch[0]=tree[x].fa=0;up(y);} int query(int k){if (!k) return 0;makeroot(1);access(k),splay(k);return tree[k].s-tree[lson].s;} void decode(int mask) { for (int j=0;j<m;j++) { mask=(mask*131+j)%m; char u=t[j];t[j]=t[mask];t[mask]=u; } } void relink(int x,int y) { if (fail[x]) cut(x,fail[x]); fail[x]=y;link(x,y); } void ins(int c) { int x=++cnt,p=last;len[x]=len[p]+1;last=x;tree[x].x=tree[x].s=1; while (!son[p][c]&&p) son[p][c]=x,p=fail[p]; if (!p) relink(x,1); else { int q=son[p][c]; if (len[p]+1==len[q]) relink(x,q); else { int y=++cnt; len[y]=len[p]+1; memcpy(son[y],son[q],sizeof(son[q])); relink(y,fail[q]); relink(q,y); relink(x,y); while (son[p][c]==q) son[p][c]=y,p=fail[p]; } } } int run(char *s) { int k=1; for (int i=0;i<m;i++) k=son[k][s[i]-'A']; return k; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif Q=read();scanf("%s",s);n=strlen(s); for (int i=0;i<n;i++) ins(s[i]-'A'); while (Q--) { scanf("%s",t); if (t[0]=='A') { scanf("%s",t);m=strlen(t); decode(mask); for (int i=0;i<m;i++) ins(t[i]-'A'); } else { scanf("%s",t);m=strlen(t); decode(mask); int ans=query(run(t)); printf("%d\n",ans); mask^=ans; } } return 0; }