2555: SubString
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
如果没有添加的操作的话,我们直接建立SAM然后查询r的大小即可。。。
但是因为我们要添加,所以可以想到我们每次实际上是把当前节点到根的路径上的r++,所以用lct。。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #define N 1200005 8 #define inf 1000000000 9 using namespace std; 10 int mask; 11 char s[3000005]; 12 string chars; 13 void gets(int mask) 14 { 15 scanf("%s",s); 16 chars=s; 17 for (int j=0;j<chars.length();j++) 18 { 19 mask=(mask*131+j)%chars.length(); 20 char t=chars[j]; 21 chars[j]=chars[mask]; 22 chars[mask]=t; 23 } 24 } 25 struct lct 26 { 27 int top; 28 int fa[N],c[N][2],w[N],tag[N],q[N]; 29 bool rev[N]; 30 void add(int x,int y){ 31 if(x) 32 { 33 w[x]+=y;tag[x]+=y; 34 } 35 } 36 void pushdown(int x){ 37 int l=c[x][0],r=c[x][1]; 38 if(tag[x]) 39 { 40 add(l,tag[x]);add(r,tag[x]); 41 tag[x]=0; 42 } 43 } 44 bool isroot(int x){ 45 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 46 } 47 void rotate(int x){ 48 int y=fa[x],z=fa[y],l,r; 49 if(c[y][0]==x)l=0;else l=1;r=l^1; 50 if(!isroot(y)) 51 { 52 if(c[z][0]==y)c[z][0]=x; 53 else c[z][1]=x; 54 } 55 fa[c[x][r]]=y;fa[y]=x;fa[x]=z; 56 c[y][l]=c[x][r];c[x][r]=y; 57 } 58 void splay(int x){ 59 top=0;q[++top]=x; 60 for(int i=x;!isroot(i);i=fa[i]) 61 q[++top]=fa[i]; 62 for(int i=top;i;i--) 63 pushdown(q[i]); 64 while(!isroot(x)) 65 { 66 int y=fa[x],z=fa[y]; 67 if(!isroot(y)) 68 { 69 if(c[y][0]==x^c[z][0]==y)rotate(x); 70 else rotate(y); 71 } 72 rotate(x); 73 } 74 } 75 void access(int x){ 76 for(int t=0;x;t=x,x=fa[x]) 77 splay(x),c[x][1]=t; 78 } 79 void link(int x,int f){ 80 fa[x]=f;access(f);splay(f);add(f,w[x]); 81 } 82 void cut(int x){ 83 access(x);splay(x);add(c[x][0],-w[x]); 84 fa[c[x][0]]=0;c[x][0]=0; 85 } 86 }t; 87 struct sam 88 { 89 int l[N],fa[N],to[N][26]; 90 int cnt,last; 91 int p,np,q,nq; 92 sam(){ 93 last=++cnt; 94 } 95 void extend(int c){ 96 p=last;last=np=++cnt;t.w[np]=1;l[np]=l[p]+1; 97 for(;p&&!to[p][c];p=fa[p])to[p][c]=np; 98 if(!p)fa[np]=1,t.link(np,1); 99 else 100 { 101 q=to[p][c]; 102 if(l[p]+1==l[q])fa[np]=q,t.link(np,q); 103 else 104 { 105 nq=++cnt;l[nq]=l[p]+1; 106 memcpy(to[nq],to[q],sizeof(to[q])); 107 fa[nq]=fa[q]; 108 t.link(nq,fa[q]); 109 fa[np]=fa[q]=nq; 110 t.cut(q);t.link(q,nq);t.link(np,nq); 111 for(;to[p][c]==q;p=fa[p])to[p][c]=nq; 112 } 113 } 114 } 115 void build(){ 116 scanf("%s",s); 117 int l=strlen(s); 118 for(int i=0;i<l;i++) 119 extend(s[i]-'A'); 120 } 121 void add(){ 122 gets(mask); 123 int l=chars.length(); 124 for(int i=0;i<l;i++) 125 extend(chars[i]-'A'); 126 } 127 int query(){ 128 gets(mask); 129 int p=1,l=chars.length(); 130 for(int i=0;i<l;i++) 131 if(!(p=to[p][chars[i]-'A']))return 0; 132 t.splay(p); 133 return t.w[p]; 134 } 135 }sam; 136 int main() 137 { 138 int Q;scanf("%d",&Q); 139 sam.build(); 140 while(Q--) 141 { 142 scanf("%s",s); 143 if(s[0]=='A')sam.add(); 144 else 145 { 146 int ans=sam.query(); 147 printf("%d\n",ans); 148 mask^=ans; 149 } 150 } 151 return 0; 152 }