[BZOJ2555]SubString LCT+后缀自动机
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 3253 Solved: 975
[Submit][Status][Discuss]
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
Source
显然我们要求当前子串子树的后缀结束结点个数。
要在线实现,用lct维护sam
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define maxn 1200000 8 using namespace std; 9 int mask; 10 char st[3000005]; 11 string chars; 12 void gets(int mask) { 13 scanf("%s",st); 14 chars=st; 15 for(int j=0;j<chars.length();j++) { 16 mask=(mask*131+j)%chars.length(); 17 char t=chars[j]; 18 chars[j]=chars[mask]; 19 chars[mask]=t; 20 } 21 } 22 struct data { 23 int last,cnt; 24 int son[maxn][26],link[maxn],step[maxn]; 25 data() {last=cnt=1;} 26 struct lct { 27 int fa[maxn],s[maxn][2],v[maxn],tag[maxn]; 28 bool isroot(int x) {return s[fa[x]][1]!=x&&s[fa[x]][0]!=x;} 29 void add(int x,int y){if(x) v[x]+=y,tag[x]+=y;} 30 void pushdown(int x) { 31 if(tag[x]) { 32 add(s[x][0],tag[x]);add(s[x][1],tag[x]); 33 tag[x]=0; 34 } 35 } 36 void push(int x) { 37 if(!isroot(x)) push(fa[x]); 38 pushdown(x); 39 } 40 void rorate(int x) { 41 int y=fa[x],z=fa[y]; 42 bool l=(s[y][1]==x),r=l^1; 43 if(!isroot(y)) s[z][s[z][1]==y]=x; 44 fa[x]=z;fa[y]=x;s[y][l]=s[x][r]; 45 fa[s[x][r]]=y;s[x][r]=y; 46 } 47 void splay(int x) { 48 push(x); 49 while(!isroot(x)) { 50 int y=fa[x],z=fa[y]; 51 if(!isroot(y)) { 52 if(s[y][0]==x^s[z][0]==y) rorate(x); 53 else rorate(y); 54 } 55 rorate(x); 56 } 57 } 58 void access(int x) {for(int t=0;x;t=x,x=fa[x]) {splay(x);s[x][1]=t;}} 59 void link(int x,int y) {fa[x]=y;access(y);splay(y);add(y,v[x]);} 60 void cut(int x) {access(x);splay(x);add(s[x][0],-v[x]);s[x][0]=fa[s[x][0]]=0;} 61 }t; 62 void extend(int c) { 63 int p=last,np=last=++cnt;step[np]=step[p]+1;t.v[np]=1; 64 while(p&&!son[p][c]) son[p][c]=np,p=link[p]; 65 if(!p) link[np]=1,t.link(np,1); 66 else { 67 int q=son[p][c]; 68 if(step[q]==step[p]+1) link[np]=q,t.link(np,q); 69 else { 70 int nq=++cnt; 71 memcpy(son[nq],son[q],sizeof(son[q])); 72 link[nq]=link[q];t.link(nq,link[q]); 73 link[q]=link[np]=nq; 74 t.cut(q);t.link(np,nq);t.link(q,nq); 75 step[nq]=step[p]+1; 76 while(son[p][c]==q&&p) son[p][c]=nq,p=link[p]; 77 } 78 } 79 } 80 void add() { 81 gets(mask); 82 int l=chars.length(); 83 for(int i=0;i<l;i++) extend(chars[i]-'A'); 84 } 85 int query() { 86 gets(mask); 87 int p=1,l=chars.length(); 88 for(int i=0;i<l;i++) { 89 p=son[p][chars[i]-'A'];if(!p) return 0; 90 } 91 t.splay(p); 92 return t.v[p]; 93 } 94 }sam; 95 int main() { 96 int Q;scanf("%d",&Q); 97 scanf("%s",st+1); 98 int len=strlen(st+1); 99 for(int i=1;i<=len;i++) sam.extend(st[i]-'A'); 100 while(Q--) { 101 char s[10]; 102 scanf("%s",s); 103 if(s[0]=='A') sam.add(); 104 else { 105 int ans=sam.query(); 106 printf("%d\n",ans); 107 mask^=ans; 108 } 109 } 110 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~