bzoj2555(lct维护sam)

题意:
  (1):在当前字符串的后面插入一个字符串
  (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
  字符串长度<=6e5,询问总长度<=3e6
分析:
  考虑建个sam,然后把slink连起来就形成了一个前缀树
  对于每个询问的串,就是求出它在sam里对应的点,然后在slink树种该点子树的size就是答案
  用lct维护slink树即可
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1200000;
  4 const int maxs=3e6;
  5 
  6 struct LCT
  7 {
  8     int ch[maxn+5][2],fa[maxn+5],flip[maxn+5];
  9     int top;
 10     int q[maxn+5];
 11     int sz[maxn+5];
 12     int tag[maxn+5];
 13     void init()
 14     {
 15 
 16     }
 17     bool isroot(int x)
 18     {
 19         return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 20     }
 21     void add(int x,int data)
 22     {
 23         if(x)
 24         {
 25             tag[x]+=data;
 26             sz[x]+=data;
 27         }
 28     }
 29     void pushdown(int x)
 30     {
 31         int l=ch[x][0],r=ch[x][1];
 32         if(flip[x])
 33         {
 34             flip[x]^=1;flip[l]^=1;flip[r]^=1;
 35             swap(ch[x][0],ch[x][1]);
 36         }
 37         if(tag[x])
 38         {
 39             add(l,tag[x]),add(r,tag[x]);
 40             tag[x]=0;
 41         }
 42     }
 43     void rotate(int &x)
 44     {
 45         int y=fa[x],z=fa[y],l,r;
 46         if(ch[y][0]==x) l=0;
 47         else l=1;
 48         r=l^1;
 49         if(!isroot(y))
 50         {
 51             if(ch[z][0]==y) ch[z][0]=x;
 52             else ch[z][1]=x;
 53         }
 54         fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
 55         ch[y][l]=ch[x][r];ch[x][r]=y;
 56     }
 57     void splay(int &x)
 58     {
 59         top=0;
 60         q[++top]=x;
 61         for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
 62         while(top) pushdown(q[top--]);
 63         while(!isroot(x))
 64         {
 65             int y=fa[x],z=fa[y];
 66             if(!isroot(y))
 67             {
 68                 if(ch[y][0]==x^ch[z][0]==y) rotate(x);
 69                 else rotate(y);
 70             }
 71             rotate(x);
 72         }
 73     }
 74     void access(int x)
 75     {
 76         for(int t=0;x;t=x,x=fa[x])
 77             splay(x),ch[x][1]=t;
 78     }
 79     void link(int x,int f)
 80     {
 81         fa[x]=f;
 82         access(f);
 83         splay(f);
 84         add(f,sz[x]);
 85     }
 86     void cut(int x)
 87     {
 88         access(x);
 89         splay(x);
 90         add(ch[x][0],-sz[x]);
 91         fa[ch[x][0]]=0,ch[x][0]=0;
 92     }
 93     int query(int x)
 94     {
 95         access(x);
 96         splay(x);
 97         return sz[x];
 98     }
 99 }lct;
100 
101 struct SAM
102 {
103     int maxlen[maxn+50],minlen[maxn+50],trans[maxn+50][26],slink[maxn+50];
104     int sz,last;
105     void init()
106     {
107         for(int i=0;i<26;++i) trans[1][i]=slink[1]=-1;
108         maxlen[1]=minlen[1]=0;
109         sz=1;
110         last=1;
111     }
112     int build(int _maxlen,int _minlen,int* _trans,int _slink)
113     {
114         maxlen[++sz]=_maxlen;
115         minlen[sz]=_minlen;
116         for(int i=0;i<26;++i)
117             if(_trans==NULL) trans[sz][i]=-1;else trans[sz][i]=_trans[i];
118         slink[sz]=_slink;
119         return sz;
120     }
121     int add(char ch,int u)
122     {
123         int c=ch-'A';
124         int z=build(maxlen[u]+1,-1,NULL,-1);
125         lct.sz[z]=1;
126         int v=u;
127         while(v!=-1&&trans[v][c]==-1)
128         {
129             trans[v][c]=z,v=slink[v];
130         }
131         if(v==-1)//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
132         {
133             minlen[z]=1;
134             slink[z]=1;
135             lct.link(z,1);
136             return z;
137         }
138         int x=trans[v][c];
139         if(maxlen[v]+1==maxlen[x])//较简单的情况,不用拆分x
140         {
141             minlen[z]=maxlen[x]+1;
142             slink[z]=x;
143             lct.link(z,x);
144             return z;
145         }
146         int y=build(maxlen[v]+1,-1,trans[x],slink[x]); //最复杂的情况,拆分x,y表示<=maxlen[v]+1的那段
147         slink[y]=slink[x];
148         lct.link(y,slink[y]);
149         minlen[x]=maxlen[y]+1;
150         lct.cut(x);
151         slink[x]=y;
152         lct.link(x,y);
153         minlen[z]=maxlen[y]+1;
154         slink[z]=y;
155         lct.link(z,y);
156         int w=v;
157         while(w!=-1&&trans[w][c]==x) trans[w][c]=y,w=slink[w];
158         minlen[y]=maxlen[slink[y]]+1;
159         return z;
160     }
161     void append(char *s)
162     {
163         int len=strlen(s);
164         for(int i=0;i<len;++i) last=add(s[i],last);
165     }
166     int query(char *s)
167     {
168         int len=strlen(s);
169         int now=1;
170         for(int i=0;i<len;++i)
171         {
172             now=trans[now][s[i]-'A'];
173             if(now==-1) return 0;
174         }
175         return lct.query(now);
176     }
177 }sam;
178 char s[maxs+5];
179 int mask=0;
180 void gets(int mask)
181 {
182     scanf("%s",s);
183     int len=strlen(s);
184     for (int j=0;j<len;j++)
185     {
186         mask=(mask*131+j)%len;
187         char t=s[j];
188         s[j]=s[mask];
189         s[mask]=t;
190     }
191 }
192 int main()
193 {
194     int q;
195     scanf("%d",&q);
196     sam.init();
197     scanf("%s",s);
198     sam.append(s);
199     while(q--)
200     {
201         scanf("%s",s);
202         if(s[0]=='A')
203         {
204             gets(mask);
205             sam.append(s);
206         }
207         else
208         {
209             gets(mask);
210             int ans=sam.query(s);
211             mask^=ans;
212             printf("%d\n",ans);
213         }
214     }
215     return 0;
216 }
View Code

 

posted @ 2018-04-17 00:02  Chellyutaha  阅读(432)  评论(0编辑  收藏  举报