1. 程式人生 > >[BZOJ2555]SubString(SAM+LCT)

[BZOJ2555]SubString(SAM+LCT)

out 數據 tps 要求 n) gre efi bmi 需要

2555: SubString

Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 4077 Solved: 1236
[Submit][Status][Discuss]

Description

懶得寫背景了,給你一個字符串init,要求你支持兩個操作 (1):在當前字符串的後面插入一個字符串 (2):詢問字符串s在當前字符串中出現了幾次?(作為連續子串) 你必須在線支持這些操作。

Input

第一行一個數Q表示操作個數 第二行一個字符串表示初始字符串init 接下來Q行,每行2個字符串Type,Str Type是ADD的話表示在後面插入字符串。 Type是QUERY的話表示詢問某字符串在當前字符串中出現了幾次。 為了體現在線操作,你需要維護一個變量mask,初始值為0

技術分享圖片

讀入串Str之後,使用這個過程將之解碼成真正詢問的串TrueStr。 詢問的時候,對TrueStr詢問後輸出一行答案Result 然後mask=maskxorResult 插入的時候,將TrueStr插到當前字符串後面即可。 HINT:ADD和QUERY操作的字符串都需要解壓 長度 <= 600000,詢問次數<= 10000,詢問總長度<= 3000000 新加數據一組--2015.05.20

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

HINT

Source

Ctsc模擬賽By 潔妹

[Submit][Status][Discuss]

後綴自動機,每次查詢的是一個點的Right。

發現每次改變fa[]實際上是在pre樹上的一次Cut和Link操作,所以用LCT維護就好了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ls ch[x][0]
 5 #define rs ch[x][1]
 6 #define rep(i,l,r) for (int i=l; i<=r; i++)
 7 using namespace
std; 8 9 const int N=1200010; 10 int Q,len,lst=1,cnt=1,mask,f[N],sm[N],ch[N][2],tag[N],w[N],son[N][27],mx[N],fa[N]; 11 char op[10],S[3000100]; 12 13 bool isroot(int x){ return (!f[x]) || (ch[f[x]][0]!=x && ch[f[x]][1]!=x); } 14 void put(int x,int k){ w[x]+=k; tag[x]+=k; } 15 void push(int x){ if (tag[x]) put(ls,tag[x]),put(rs,tag[x]),tag[x]=0; } 16 void pd(int x){ if (!isroot(x)) pd(f[x]); push(x); } 17 18 void rot(int x){ 19 int y=f[x],z=f[y],w=ch[y][1]==x; 20 if (!isroot(y)) ch[z][ch[z][1]==y]=x; 21 f[x]=z; f[y]=x; f[ch[x][w^1]]=y; 22 ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; 23 } 24 25 void splay(int x){ 26 pd(x); 27 while (!isroot(x)){ 28 int y=f[x],z=f[y]; 29 if (!isroot(y)) rot((ch[z][0]==y)^(ch[y][0]==x) ? x : y); 30 rot(x); 31 } 32 } 33 34 void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y; } 35 void link(int x,int y){ f[x]=y; access(y); splay(y); put(y,w[x]); } 36 void cut(int x){ access(x); splay(x); put(ls,-w[x]); f[ls]=0; ch[x][0]=0; } 37 int que(int x){ splay(x); return w[x]; } 38 39 void ext(int c){ 40 int p=lst,np=lst=++cnt; mx[np]=mx[p]+1; w[np]=1; 41 while (p && !son[p][c]) son[p][c]=np,p=fa[p]; 42 if (!p) fa[np]=1,link(np,1); 43 else{ 44 int q=son[p][c]; 45 if (mx[q]==mx[p]+1) fa[np]=q,link(np,q); 46 else{ 47 int nq=++cnt; mx[nq]=mx[p]+1; 48 while (p && son[p][c]==q) son[p][c]=nq,p=fa[p]; 49 memcpy(son[nq],son[q],sizeof(son[q])); 50 fa[nq]=fa[q]; link(nq,fa[q]); 51 cut(q); fa[np]=fa[q]=nq; link(np,nq); link(q,nq); 52 } 53 } 54 } 55 56 void get(int mask){ 57 scanf("%s",S); len=strlen(S); 58 for (int i=0; i<len; i++) mask=(mask*131+i)%len,swap(S[i],S[mask]); 59 } 60 61 int main(){ 62 freopen("bzoj2555.in","r",stdin); 63 freopen("bzoj2555.out","w",stdout); 64 scanf("%d",&Q); scanf("%s",S); len=strlen(S); 65 for (int i=0; i<len; i++) ext(S[i]-A+1); 66 rep(i,1,Q){ 67 scanf("%s",op); 68 if (op[0]==A){ get(mask); for (int j=0; j<len; j++) ext(S[j]-A+1); } 69 else{ 70 get(mask); int x=1,flag=0; 71 for (int j=0; j<len; j++){ 72 if (!son[x][S[j]-A+1]){ flag=1; puts("0"); break; } 73 x=son[x][S[j]-A+1]; 74 } 75 if (flag) continue; 76 int t=que(x); mask^=t; printf("%d\n",t); 77 } 78 } 79 return 0; 80 }

[BZOJ2555]SubString(SAM+LCT)