1. 程式人生 > >bzoj2555 SubString

bzoj2555 SubString

top src script tag 插入字符串 tom esc using col

Description

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

Input

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

技術分享

讀入串Str之後,使用這個過程將之解碼成真正詢問的串TrueStr。
詢問的時候,對TrueStr詢問後輸出一行答案Result
然後mask = mask xor Result
插入的時候,將TrueStr插到當前字符串後面即可。

HINT:ADD和QUERY操作的字符串都需要解壓

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

HINT

40 % 的數據字符串最終長度 <= 20000,詢問次數<= 1000,詢問總長度<= 10000

100 % 的數據字符串最終長度 <= 600000,詢問次數<= 10000,詢問總長度<= 3000000

新加數據一組--2015.05.20

正解:後綴自動機+$link-cut \ tree$。

首先我們可以對原串構後綴自動機,然後我們可以發現一個子串的個數就是它的$right$集合的大小,也就是$parent$樹的子樹。

那麽我們可以每次新建點連邊的時候用$LCT$來維護子樹大小,直接連邊以後它父親到根的路徑$+1$就行了。

  1 #include <bits/stdc++.h>
  2 #define il inline
  3 #define
RG register 4 #define ll long long 5 #define N (1200010) 6 #define M (3000010) 7 8 using namespace std; 9 10 int Q,len,ans,mask; 11 char s[M],type[M]; 12 13 struct Link_Cut_Tree{ 14 15 int ch[N][2],fa[N],st[N],val[N],tag[N],top; 16 17 il void add(RG int x,RG int v){ 18 if (x) val[x]+=v,tag[x]+=v; return; 19 } 20 21 il int isroot(RG int x){ 22 return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; 23 } 24 25 il void pushdown(RG int x){ 26 add(ch[x][0],tag[x]),add(ch[x][1],tag[x]),tag[x]=0; return; 27 } 28 29 il void rotate(RG int x){ 30 RG int y=fa[x],z=fa[y],k=ch[y][0]==x; 31 if (!isroot(y)) ch[z][ch[z][1]==y]=x; 32 fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y; 33 ch[x][k]=y,fa[y]=x; return; 34 } 35 36 il void splay(RG int x){ 37 RG int top=0; st[++top]=x; 38 for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; 39 for (RG int i=top;i;--i) if (tag[st[i]]) pushdown(st[i]); 40 while (!isroot(x)){ 41 RG int y=fa[x],z=fa[y]; 42 if (!isroot(y)) rotate((ch[z][0]==y)^(ch[y][0]==x) ? x : y); 43 rotate(x); 44 } 45 return; 46 } 47 48 il void access(RG int x){ 49 RG int t=0; 50 while (x) splay(x),ch[x][1]=t,t=x,x=fa[x]; 51 return; 52 } 53 54 il void link(RG int x,RG int y){ 55 fa[x]=y,access(y),splay(y),add(y,val[x]); return; 56 } 57 58 il void cut(RG int x){ 59 access(x),splay(x),add(ch[x][0],-val[x]); 60 fa[ch[x][0]]=0,ch[x][0]=0; return; 61 } 62 63 il int query(RG int x){ splay(x); return val[x]; } 64 65 }LCT; 66 67 struct Suffix_Automaton{ 68 69 int ch[N][26],fa[N],l[N],la,tot; 70 71 il void init(){ la=++tot; return; } 72 73 il void add(RG int c){ 74 RG int p=la,np=++tot; la=np,l[np]=l[p]+1,LCT.val[np]=1; 75 for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np; 76 if (!p){ LCT.link(np,fa[np]=1); return; } 77 RG int q=ch[p][c]; 78 if (l[q]==l[p]+1) LCT.link(np,fa[np]=q); else{ 79 RG int nq=++tot; l[nq]=l[p]+1; 80 memcpy(ch[nq],ch[q],sizeof(ch[q])); 81 LCT.cut(q),LCT.link(nq,fa[nq]=fa[q]); 82 LCT.link(q,fa[q]=nq),LCT.link(np,fa[np]=nq); 83 for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 84 } 85 return; 86 } 87 88 il int query(){ 89 RG int cur=1; 90 for (RG int i=0;i<len;++i) 91 if (!(cur=ch[cur][s[i]-A])) return 0; 92 return LCT.query(cur); 93 } 94 95 }SAM; 96 97 il void trans(RG int mask){ 98 for (RG int i=0;i<len;++i) 99 swap(s[i],s[mask=(mask*131+i)%len]); 100 return; 101 } 102 103 int main(){ 104 #ifndef ONLINE_JUDGE 105 freopen("substring.in","r",stdin); 106 freopen("substring.out","w",stdout); 107 #endif 108 cin>>Q,scanf("%s",s),len=strlen(s),SAM.init(); 109 for (RG int i=0;i<len;++i) SAM.add(s[i]-A); 110 while (Q--){ 111 scanf("%s%s",type,s),len=strlen(s),trans(mask); 112 if (type[0]==A) for (RG int i=0;i<len;++i) SAM.add(s[i]-A); 113 if (type[0]==Q) printf("%d\n",ans=SAM.query()),mask^=ans; 114 } 115 return 0; 116 }

bzoj2555 SubString