字符串(LCT,后缀自动机):BZOJ 2555 SubString
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 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
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 }
尽最大的努力,做最好的自己!