字符串(LCT,后缀自动机):BZOJ 2555 SubString

Posted 既然选择了远方,便只顾风雨兼程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串(LCT,后缀自动机):BZOJ 2555 SubString相关的知识,希望对你有一定的参考价值。

2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 1620  Solved: 471

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

  注意这个mask不会在函数内改变……

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=1200010;
  6 int cnt,last;
  7 int FA[maxn],CH[maxn][27],len[maxn],rt[maxn];
  8 int fa[maxn],ch[maxn][2],add[maxn],key[maxn],flip[maxn];
  9 
 10 void Add(int x,int d){
 11     if(!x)return;
 12     key[x]+=d;
 13     add[x]+=d;
 14 }
 15 
 16 void Flip(int x){
 17     swap(ch[x][0],ch[x][1]);
 18     flip[x]^=1;
 19 }
 20 
 21 void Push_down(int x){
 22     if(add[x]){
 23         Add(ch[x][0],add[x]);
 24         Add(ch[x][1],add[x]);
 25         add[x]=0;
 26     }
 27     if(flip[x]){
 28         Flip(ch[x][0]);
 29         Flip(ch[x][1]);
 30         flip[x]=0;
 31     }
 32 }
 33 
 34 void Rotate(int x){
 35     int y=fa[x],g=fa[y],c=ch[y][1]==x;
 36     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
 37     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
 38     if(rt[y])rt[y]=false,rt[x]=true;
 39     else ch[g][ch[g][1]==y]=x;
 40 }
 41 
 42 void P(int x){
 43     if(!rt[x])P(fa[x]);
 44     Push_down(x);
 45 }
 46 
 47 void Splay(int x){
 48     P(x);
 49     for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
 50         if(!rt[y])Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);        
 51 }
 52 
 53 void Access(int x){
 54     int y=0;
 55     while(x){
 56         Splay(x);
 57         rt[ch[x][1]]=true;
 58         rt[ch[x][1]=y]=false;
 59         x=fa[y=x];
 60     }
 61 }
 62 
 63 void Lca(int &x,int &y){
 64     Access(y);y=0;
 65     while(true){
 66         Splay(x);
 67         if(!fa[x])break;
 68         rt[ch[x][1]]=true;
 69         rt[ch[x][1]=y]=false;
 70         x=fa[y=x];
 71     }
 72 }
 73 
 74 void Make_rt(int x){
 75     Access(x);
 76     Splay(x);
 77     Flip(x);
 78 }
 79 
 80 void Change(int x,int y,int d){
 81     Lca(x,y);key[x]+=d;
 82     Add(y,d);Add(ch[x][1],d);
 83 }
 84 
 85 void Link(int x,int y){
 86     Make_rt(x);
 87     Splay(x);
 88     fa[x]=y;
 89     Change(1,y,key[x]);
 90 }
 91 
 92 void Cut(int x,int y){
 93     Make_rt(x);
 94     Splay(y);
 95     fa[ch[y][0]]=fa[y];
 96     fa[y]=0;rt[ch[y][0]]=true;
 97     ch[y][0]=0;
 98     Change(1,y,-key[x]);
 99 }
100 
101 
102 
103 struct SAM{
104     void Init(){
105         memset(FA,0,sizeof(FA));
106         memset(CH,0,sizeof(CH));
107         memset(rt,-1,sizeof(rt));
108         last=cnt=1;
109     }
110     
111     void Insert(int c){
112         int p=last,np=last=++cnt;len[np]=len[p]+1;key[np]=1;
113         while(p&&!CH[p][c])CH[p][c]=np,p=FA[p];
114         if(!p)FA[np]=1;
115         else{
116             int q=CH[p][c];
117             if(len[p]+1==len[q])
118                 FA[np]=q;
119             else{
120                 int nq=++cnt;len[nq]=len[p]+1;
121                 memcpy(CH[nq],CH[q],sizeof(CH[q]));
122                 FA[nq]=FA[q];FA[q]=FA[np]=nq;
123                 
124                 Link(nq,FA[nq]);Cut(q,FA[nq]);Link(q,nq);
125                 
126                 while(CH[p][c]==q)
127                     CH[p][c]=nq,p=FA[p];
128             }    
129         }
130         Link(np,FA[np]);
131     }
132     void Extend(char *s){
133         int l=strlen(s);
134         for(int i=0;i<l;i++)
135             Insert(s[i]-A);
136     }
137     
138     int Solve(char *s){
139         int l=strlen(s),p=1;
140         for(int i=0,c;i<l;i++){
141             c=s[i]-A;
142             if(!CH[p][c])return 0;
143             else p=CH[p][c];
144         }
145         Splay(p);
146         return key[p];
147     }
148 }sam;
149 
150 char s[maxn];
151 char op[10];
152 int ans,mask,Q;
153 
154 void Decode(char *str,int t){
155     int l=strlen(str);
156     for(int i=0;i<l;i++){
157         t=(t*131+i)%l;
158         swap(str[i],str[t]);
159     }
160 }
161 
162 int main(){
163     sam.Init();
164     scanf("%d",&Q);
165     scanf("%s",s);
166     sam.Extend(s);
167     while(Q--){
168         scanf("%s",op);
169         scanf("%s",s);Decode(s,mask);
170         if(op[0]==A)
171             sam.Extend(s);
172         else{
173             ans=sam.Solve(s);
174             printf("%d\n",ans);
175             mask^=ans;
176         }
177     }
178     return 0;
179 }

 

以上是关于字符串(LCT,后缀自动机):BZOJ 2555 SubString的主要内容,如果未能解决你的问题,请参考以下文章

字符串(LCT,后缀自动机):BZOJ 2555 SubString

BZOJ 2555: SubString [后缀自动机 LCT]

BZOJ 2555 SubString 后缀自动机+LCT

bzoj 2555 SubString —— 后缀自动机+LCT

bzoj 2555 SubString——后缀自动机+LCT

bzoj2555 SubString