1. 程式人生 > >bzoj 2555 SubString——後綴自動機+LCT

bzoj 2555 SubString——後綴自動機+LCT

mask top == name return can 什麽 bst names

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555

要維護 right 集合的大小。因為 fa 會變,且 fa 構成一棵樹,所以考慮用 LCT 來維護……

和平常寫的 LCT 不太一樣。因為要的值是原樹上子樹裏的值,所以沒有 makeroot ,splay 裏不維護 splay 裏的子樹信息,只維護加法標記,表示 link 一下就給原樹的自己到根的那條鏈上的所有點加了自己的值。cut 就是減掉自己的值。所以 query 或者 splay 的時候先把自己這棵 splay 裏自己到根的路徑 pshd 一遍,且沒有 pshp 什麽的。而且 link 時要區分兩個點哪個是原樹上的父親。

不知怎麽看出字符只有大寫字母的。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1200005,K=30,M=3e6+5;
int cnt=1,lst=1,go[N][K],fa[N],l[N],mask;
int c[N][2],pre[N],sta[N],top,sm[N],tg[N];
char ch[M];
void decodeWithMask(int n,int mask)
{
  for(int i=0;i<n;i++)
    {
      mask
=(mask*131+i)%n; swap(ch[i],ch[mask]); } } bool isroot(int x){return c[pre[x]][0]!=x&&c[pre[x]][1]!=x;} void pshd(int x) { if(!tg[x])return;int ls=c[x][0],rs=c[x][1]; sm[ls]+=tg[x];tg[ls]+=tg[x];sm[rs]+=tg[x];tg[rs]+=tg[x]; tg[x]=0; } void Pshd(int x) { sta[top=1]=x; for(;!isroot(x);x=pre[x])sta[++top]=pre[x];
for(int i=top;i;i--)pshd(sta[i]); } void rotate(int x) { int y=pre[x],z=pre[y]; if(!isroot(y))c[z][y==c[z][1]]=x; pre[x]=z; int d=(x==c[y][1]); pre[c[x][!d]]=y; pre[y]=x; c[y][d]=c[x][!d]; c[x][!d]=y; } void splay(int x) { Pshd(x); while(!isroot(x)) { int y=pre[x],z=pre[y]; if(!isroot(y)) { if((y==c[z][0])^(x==c[y][0]))rotate(x); else rotate(y); } rotate(x); } } void access(int x) { for(int t=0;x;splay(x),c[x][1]=t,t=x,x=pre[x]); } void link(int x,int y) { pre[y]=x;access(x);splay(x); sm[x]+=sm[y]; tg[x]+=sm[y];//tg:pre of x all added } void cut(int x) { access(x);splay(x); sm[c[x][0]]-=sm[x]; tg[c[x][0]]-=sm[x];//tg:pre of x all declined pre[c[x][0]]=0; c[x][0]=0; } void add(int w) { int p=lst,np=++cnt;lst=np;l[np]=l[p]+1;sm[np]=1; for(;p&&!go[p][w];p=fa[p])go[p][w]=np; if(!p)fa[np]=1,link(1,np); else { int q=go[p][w]; if(l[q]==l[p]+1)fa[np]=q,link(q,np); else { int nq=++cnt;l[nq]=l[p]+1; cut(q);link(fa[q],nq);link(nq,q);link(nq,np);/// fa[nq]=fa[q];fa[q]=nq;fa[np]=nq;//after link&cut ! memcpy(go[nq],go[q],sizeof go[q]); for(;go[p][w]==q;p=fa[p])go[p][w]=nq; } } } int query(int len) { int cr=1; for(int i=0;i<len;i++) { if(!go[cr][ch[i]-A+1])return 0; cr=go[cr][ch[i]-A+1]; } Pshd(cr); return sm[cr]; } int main() { int Q;scanf("%d",&Q);scanf("%s",ch); int n=strlen(ch);for(int i=0;i<n;i++)add(ch[i]-A+1); char tch[10]; while(Q--) { scanf("%s",tch);scanf("%s",ch);n=strlen(ch); decodeWithMask(n,mask); if(tch[0]==A) { for(int i=0;i<n;i++)add(ch[i]-A+1); } else { int d=query(n);printf("%d\n",d); mask^=d; } } return 0; }

bzoj 2555 SubString——後綴自動機+LCT