1. 程式人生 > >【BZOJ2555】SubString(後綴自動機,Link-Cut Tree)

【BZOJ2555】SubString(後綴自動機,Link-Cut Tree)

cstring 一個 put ostream bzoj2555 subst get ini void

【BZOJ2555】SubString(後綴自動機,Link-Cut Tree)

題面

BZOJ

題解

這題看起來不難
每次要求的就是\(right/endpos\)集合的大小
所以搞一個\(LCT\)維護一下\(SAM\)\(Parent\)樹就好了
但是代碼一點都不好寫(我還是對著黃學長的調的。。。)
於是乎我也學著魔改了一下\(LCT\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 600006 char ch[MAX]; inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1
,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int mask,ans; struct LCT { #define lson (t[x].ch[0]) #define rson (t[x].ch[1]) struct Node { int ch[2],ff; int rev,v,ly; }t[MAX<<1]; int S[MAX<<1
],top; bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;} void rotate(int x) { int y=t[x].ff,z=t[y].ff; int k=t[y].ch[1]==x; if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z; t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y; t[x].ch[k^1]=y;t[y].ff=x; } void putrev(int x){swap(lson,rson);t[x].rev^=1;} void putly(int x,int v){t[x].v+=v;t[x].ly+=v;} void pushdown(int x) { if(t[x].rev) { if(lson)putrev(lson); if(rson)putrev(rson); t[x].rev^=1; } if(t[x].ly!=0) { if(lson)putly(lson,t[x].ly); if(rson)putly(rson,t[x].ly); t[x].ly=0; } } void Splay(int x) { S[top=1]=x; for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff; while(top)pushdown(S[top--]); while(!isroot(x)) { int y=t[x].ff,z=t[y].ff; if(!isroot(y)) (t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y); rotate(x); } } void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),rson=y;} void makeroot(int x){access(x);Splay(x);putrev(x);} void split(int x,int y){makeroot(x);access(y);Splay(y);} void cut(int x){access(x);Splay(x);putly(lson,-t[x].v);t[lson].ff=0;lson=0;} void link(int x,int f){t[x].ff=f;access(f);Splay(f);putly(f,t[x].v);} int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;} }LCT; struct SAM { struct Node { int son[26]; int ff,len; }t[MAX<<1]; int last,tot; void init(){last=tot=1;} void extend(int c) { int p=last,np=++tot;last=np;LCT.t[np].v=1; while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff; if(!p)t[np].ff=1,LCT.link(np,1); else { int q=t[p].son[c]; if(t[q].len==t[p].len+1)t[np].ff=q,LCT.link(np,q); else { int nq=++tot; t[nq]=t[q]; t[nq].len=t[p].len+1; LCT.link(nq,t[q].ff); t[q].ff=t[np].ff=nq; LCT.cut(q);LCT.link(q,nq);LCT.link(np,nq); while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff; } } } }SAM; void Decode(char *ch,int mask) { int l=strlen(ch); for(int i=0;i<l;++i) { mask=(mask*131+i)%l; swap(ch[i],ch[mask]); } } int main() { int Q=read(); SAM.init(); scanf("%s",ch+1); for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A'); while(Q--) { scanf("%s",ch); if(ch[0]=='A') { scanf("%s",ch+1); Decode(ch+1,mask); for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A'); } else { scanf("%s",ch+1); Decode(ch+1,mask); int now=1; for(int i=1,l=strlen(ch+1);i<=l;++i) now=SAM.t[now].son[ch[i]-'A']; if(!now)printf("%d\n",ans=0); else { LCT.Splay(now); printf("%d\n",ans=LCT.t[now].v); } mask^=ans; } } return 0; }

【BZOJ2555】SubString(後綴自動機,Link-Cut Tree)