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
",lasans);
256             U.update(lasans);
257         }
258     }
259     return 0;
260 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/10046348.html