1. 程式人生 > >BZOJ2555: SubString(字尾自動機,LCT維護Parent樹)

BZOJ2555: SubString(字尾自動機,LCT維護Parent樹)

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

解題思路:

從字尾自動機構造的時候入手,因為Parent樹是與pre指標直接相關,就在pre指標構造的時候快速維護Parent(LCT)。 剩下的就是兩個模板堆疊,沒什麼思維含量。 程式碼:
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6
#define ls ch[0] 7 #define rs ch[1] 8 class Unzip{ 9 public: 10 void update(int lastans) 11 { 12 mask^=lastans; 13 return ; 14 } 15 void decode(int *a,int len) 16 { 17 int upg=mask; 18 for(int i=1;i<=len;i++) 19 tmp[i-1]=a[i]; 20 for(int i=0;i<len;i++) 21 { 22 upg=(upg*131+i)%len; 23 std::swap(tmp[i],tmp[upg]); 24 } 25 for(int i=1;i<=len;i++) 26 a[i]=tmp[i-1]; 27 return ; 28 } 29 private: 30 int tmp[1000000]; 31 int mask; 32 }U; 33 struct trnt{ 34 int ch[2]; 35 int fa; 36 int is; 37 int lzt; 38 int wgt; 39 int wgti; 40 bool anc; 41 }tr[3000000]; 42 struct sant{ 43 int tranc[26]; 44 int len; 45 int pre; 46 }s[3000000]; 47 int Q; 48 int siz; 49 int fin; 50 int lasans; 51 char tmp[1000000]; 52 int atp[1000000]; 53 bool whc(int spc) 54 { 55 return tr[tr[spc].fa].rs==spc; 56 } 57 void pushup(int spc) 58 { 59 tr[spc].wgt=tr[spc].wgti+tr[spc].is+tr[lll].wgt+tr[rrr].wgt; 60 return ; 61 } 62 void trr(int spc) 63 { 64 if(!spc) 65 return ; 66 std::swap(lll,rrr); 67 tr[spc].lzt^=1; 68 return ; 69 } 70 void pushdown(int spc) 71 { 72 if(tr[spc].lzt) 73 { 74 trr(lll); 75 trr(rrr); 76 tr[spc].lzt=0; 77 } 78 return ; 79 } 80 void recal(int spc) 81 { 82 if(!tr[spc].anc) 83 recal(tr[spc].fa); 84 pushdown(spc); 85 return ; 86 } 87 void rotate(int spc) 88 { 89 int f=tr[spc].fa; 90 bool k=whc(spc); 91 tr[f].ch[k]=tr[spc].ch[!k]; 92 tr[spc].ch[!k]=f; 93 if(tr[f].anc) 94 { 95 tr[f].anc=0; 96 tr[spc].anc=1; 97 }else 98 tr[tr[f].fa].ch[whc(f)]=spc; 99 tr[spc].fa=tr[f].fa; 100 tr[f].fa=spc; 101 tr[tr[f].ch[k]].fa=f; 102 pushup(f); 103 pushup(spc); 104 return ; 105 } 106 void splay(int spc) 107 { 108 recal(spc); 109 while(!tr[spc].anc) 110 { 111 int f=tr[spc].fa; 112 if(tr[f].anc) 113 { 114 rotate(spc); 115 return ; 116 } 117 if(whc(spc)^whc(f)) 118 rotate(spc); 119 else 120 rotate(f); 121 rotate(spc); 122 } 123 return ; 124 } 125 void access(int spc) 126 { 127 int lst=0; 128 while(spc) 129 { 130 splay(spc); 131 tr[spc].wgti-=tr[lst].wgt; 132 tr[spc].wgti+=tr[rrr].wgt; 133 tr[rrr].anc=1; 134 tr[lst].anc=0; 135 rrr=lst; 136 pushup(spc); 137 lst=spc; 138 spc=tr[spc].fa; 139 } 140 return ; 141 } 142 void Mtr(int spc) 143 { 144 access(spc); 145 splay(spc); 146 trr(spc); 147 return ; 148 } 149 void split(int x,int y) 150 { 151 Mtr(x); 152 access(y); 153 splay(y); 154 return ; 155 } 156 void link(int x,int y) 157 { 158 split(x,y); 159 tr[x].fa=y; 160 tr[y].wgti+=tr[x].wgt; 161 pushup(y); 162 return ; 163 } 164 void cut(int x,int y) 165 { 166 split(x,y); 167 tr[x].fa=0; 168 tr[y].ls=0; 169 tr[x].anc=1; 170 pushup(y); 171 return ; 172 } 173 void Insert(int c) 174 { 175 int nwp,nwq,lsp,lsq; 176 nwp=++siz; 177 tr[nwp].anc=1; 178 tr[nwp].is=1; 179 s[nwp].len=s[fin].len+1; 180 for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre) 181 s[lsp].tranc[c]=nwp; 182 if(!lsp) 183 { 184 s[nwp].pre=1; 185 link(nwp,1); 186 }else{ 187 lsq=s[lsp].tranc[c]; 188 if(s[lsq].len==s[lsp].len+1) 189 { 190 s[nwp].pre=lsq; 191 link(nwp,lsq); 192 }else{ 193 nwq=++siz; 194 tr[nwq].anc=1; 195 s[nwq]=s[lsq]; 196 cut(s[lsq].pre,lsq); 197 link(s[nwq].pre,nwq); 198 s[nwq].len=s[lsp].len+1; 199 s[nwp].pre=s[lsq].pre=nwq; 200 link(nwq,nwp); 201 link(nwq,lsq); 202 while(s[lsp].tranc[c]==lsq) 203 { 204 s[lsp].tranc[c]=nwq; 205 lsp=s[lsp].pre; 206 } 207 } 208 } 209 fin=nwp; 210 return ; 211 } 212 int Query(int root) 213 { 214 Mtr(1); 215 access(root); 216 return tr[root].wgti+tr[root].is; 217 } 218 int main() 219 { 220 fin=++siz; 221 tr[fin].anc=1; 222 scanf("%d",&Q); 223 scanf("%s",tmp+1); 224 int len=strlen(tmp+1); 225 for(int i=1;i<=len;i++) 226 Insert(tmp[i]-'A'); 227 while(Q--) 228 { 229 scanf("%s",tmp); 230 if(tmp[0]=='A') 231 { 232 scanf("%s",tmp+1); 233 len=strlen(tmp+1); 234 for(int i=1;i<=len;i++) 235 atp[i]=tmp[i]-'A'; 236 U.decode(atp,len); 237 for(int i=1;i<=len;i++) 238 Insert(atp[i]); 239 }else{ 240 scanf("%s",tmp+1); 241 len=strlen(tmp+1); 242 for(int i=1;i<=len;i++) 243 atp[i]=tmp[i]-'A'; 244 U.decode(atp,len); 245 int root=1; 246 for(int i=1;i<=len;i++) 247 { 248 root=s[root].tranc[atp[i]]; 249 250 } 251 if(!root) 252 lasans=0; 253 else 254 lasans=Query(root); 255 printf("%d\n",lasans); 256 U.update(lasans); 257 } 258 } 259 return 0; 260 }