【BZOJ 2555】 2555: SubString (SAM+LCT)

2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 2548  Solved: 762

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

   

Source

 

【分析】

  一开始都没想着用LCT,后来发现我的SAM的right数组一直都是要逆拓扑序求的。

  在线的话,还要在线维护。把pre边看成一棵树,就是要支持link,cut操作的,求子树和的东西。

  其实LCT我只会做路径的,不会做子树了。看了hzwer的代码。【然后好像是,其实也是维护了路径,就是link x和f 的时候就是把f到根的路径都加上val[x]

  【ORZ欧颓果说用splay维护dfs序也可以啊?

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 600010
  8 #define Maxl 3000010
  9 
 10 struct node
 11 {
 12     int pre,son[30],step;
 13 }t[Maxn*2];
 14 
 15 struct nnode
 16 {
 17     int son[2],fa,val,laz;
 18     nnode() {son[0]=son[1]=fa=val=laz=0;}
 19 }tr[Maxn*2];
 20 
 21 char s[Maxl];
 22 void init(int mask)
 23 {
 24     scanf("%s",s);
 25     int l=strlen(s);
 26     for(int i=0;i<l;i++)
 27     {
 28         mask=(mask*131+i)%l;
 29         swap(s[i],s[mask]);
 30     }
 31 }
 32 
 33 struct lct
 34 {
 35     void add(int x,int y)
 36     {
 37         if(x) tr[x].val+=y,tr[x].laz+=y;
 38     }
 39     bool is_root(int x)
 40     {
 41         return tr[tr[x].fa].son[0]!=x&&tr[tr[x].fa].son[1]!=x;
 42     }
 43     bool pushdown(int x)
 44     {
 45         int lc=tr[x].son[0],rc=tr[x].son[1];
 46         if(tr[x].laz)
 47         {
 48             add(lc,tr[x].laz);add(rc,tr[x].laz);
 49             tr[x].laz=0;
 50         }
 51     }
 52     void rot(int x)
 53     {
 54         int fa=tr[x].fa,yy=tr[fa].fa;
 55         int w=tr[tr[x].fa].son[0]==x;
 56         
 57         if(!is_root(fa))
 58         {
 59             if(tr[yy].son[0]==fa) tr[yy].son[0]=x;
 60             else tr[yy].son[1]=x;
 61         }tr[x].fa=yy;
 62         
 63         tr[fa].son[1-w]=tr[x].son[w];
 64         tr[tr[x].son[w]].fa=fa;
 65         
 66         tr[x].son[w]=fa;
 67         tr[fa].fa=x;
 68         //upd(fa);//upd(x);
 69     }
 70     int q[2*Maxn];
 71     void pre(int x)
 72     {
 73         int tp=0;
 74         while(!is_root(x)) q[++tp]=x,x=tr[x].fa;
 75         q[++tp]=x;
 76         for(int i=tp;i>=1;i--) pushdown(q[i]);
 77     }
 78     void splay(int x)
 79     {
 80         pre(x);
 81         while(!is_root(x))
 82         {
 83             int fa=tr[x].fa,yy=tr[fa].fa;
 84             if(!is_root(fa))
 85             {
 86                 if((tr[yy].son[0]==fa)==(tr[fa].son[0]==x)) rot(fa);
 87                 else rot(x);
 88             }
 89             rot(x);
 90         }//upd(x);
 91     }
 92     void access(int x)
 93     {
 94         int t=0;
 95         while(x)
 96         {
 97             splay(x);
 98             tr[x].son[1]=t;
 99             t=x;
100             x=tr[x].fa;
101         }
102     }
103     /*void split(int x,int y)
104     {
105         make_root(x);
106         access(y);
107         splay(y);
108     }*/
109     void link(int x,int f)
110     {
111         tr[x].fa=f;
112         access(f);
113         splay(f);
114         add(f,tr[x].val);
115     }
116     void cut(int x)
117     {
118         access(x);splay(x);
119         add(tr[x].son[0],-tr[x].val);
120         tr[tr[x].son[0]].fa=0;
121         tr[x].son[0]=0;
122     }
123 }lct;
124 
125 int mask;
126 struct sam
127 {
128     int last,tot;
129     void extend(int k)
130     {
131         int np=++tot,p=last;
132         t[np].step=t[p].step+1;
133         tr[np].val=1;
134         while(p&&!t[p].son[k])
135         {
136             t[p].son[k]=np;
137             p=t[p].pre;
138         }
139         if(!p) t[np].pre=1,lct.link(np,1);
140         else
141         {
142             int q=t[p].son[k];
143             if(t[q].step==t[p].step+1) t[np].pre=q,lct.link(np,q);
144             else
145             {
146                 int nq=++tot;//upd(tot);
147                 t[nq].step=t[p].step+1;
148                 memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
149                 t[nq].pre=t[q].pre;
150                 lct.link(nq,t[nq].pre);
151                 t[q].pre=t[np].pre=nq;
152                 lct.cut(q);lct.link(q,nq);lct.link(np,nq);
153                 while(p&&t[p].son[k]==q)
154                 {
155                     t[p].son[k]=nq;
156                     p=t[p].pre;
157                 }
158             }
159         }
160         last=np;
161     }
162     void add()
163     {
164         init(mask);
165         int l=strlen(s);
166         for(int i=0;i<l;i++) extend(s[i]-'A'+1);
167     }
168     int query()
169     {
170         init(mask);
171         int nw=1,l=strlen(s);
172         for(int i=0;i<l;i++)
173         {
174             int ind=s[i]-'A'+1;
175             if(!t[nw].son[ind]) return 0;
176             nw=t[nw].son[ind];
177         }
178         lct.splay(nw);
179         return tr[nw].val;
180     }
181 }sam;
182 
183 char ss[10];
184 
185 int main()
186 {
187     int q;
188     scanf("%d",&q);
189     sam.tot=sam.last=1;
190     scanf("%s",s);
191     int l=strlen(s);
192     for(int i=0;i<l;i++) sam.extend(s[i]-'A'+1);
193     while(q--)
194     {
195         scanf("%s",ss);
196         if(ss[0]=='A') sam.add();
197         else
198         {
199             int ans=sam.query();
200             printf("%d\n",ans);
201             mask^=ans;
202         }
203     }
204     return 0;
205 }
View Code

2017-04-19 07:48:14

posted @ 2017-04-19 07:48  konjak魔芋  阅读(248)  评论(0编辑  收藏  举报