bzoj2555 SubString
sam上维护lct,一直想做(?)一道这样的题终于在sxy的带领下做了一道最简单的模板题。
因为强制在线,又要增量的构建后缀自动机,就用lct动态维护parent树。每增加一个字符,就把它从parent树上到跟的这一段路径上的权值+1,这个可以用个懒标记维护。
然后就是后缀自动机上操作跟平时一样,只是连上父亲和新加节点换父亲等操作的时候在lct上做一遍相同操作即可。
需要注意的是加密的时候mask要传值进去,函数中mask会变但实际的mask是不变的,成功被坑 ( :。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<cstdio>
7 #include<vector>
8 #include<queue>
9 #include<cmath>
10 #include<ctime>
11 const int N=3000005;
12 typedef long long LL;
13 using namespace std;
14 int mask,Q,len;
15 string chars;
16 char s[N],op[N];
17
18 template<typename T> void read(T &x) {
19 T f=1; x=0; char ch=getchar();
20 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
21 if(ch=='-') f=-1,ch=getchar();
22 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
23 }
24
25 void gets(int mask) {
26 scanf("%s",s);
27 chars=s;
28 for (int j=0;j<chars.length();j++) {
29 mask=(mask*131+j)%chars.length();
30 char t=chars[j];
31 chars[j]=chars[mask];
32 chars[mask]=t;
33 }
34 }
35
36 #define lc ch[x][0]
37 #define rc ch[x][1]
38 struct lct{
39 int ch[N][2],p[N],sz[N],lz[N];
40
41 void down(int x) {
42 if(!lz[x]) return;
43 if(lc) { sz[lc]+=lz[x]; lz[lc]+=lz[x];}
44 if(rc) { sz[rc]+=lz[x]; lz[rc]+=lz[x];}
45 lz[x]=0;
46 }
47
48 int isroot(int x) { return (ch[p[x]][0]!=x&&ch[p[x]][1]!=x);}
49
50 void rotate(int x) {
51 int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
52 if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
53 ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
54 ch[x][r]=y; p[y]=x;
55 }
56
57 void splay(int x) {
58 static int g[N],top=0,tp;
59 for(tp=x;!isroot(tp);tp=p[tp]) g[++top]=tp;
60 g[++top]=tp;
61 while(top) down(g[top--]);
62 for(;!isroot(x);rotate(x)) {
63 int y=p[x],z=p[y];
64 if(!isroot(y))
65 ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
66 }
67 }
68
69 void access(int x) {
70 for(int t=0;x;x=p[t=x]) {
71 splay(x);
72 rc=t;
73 }
74 }
75
76 void add(int x,int v) {
77 if(!x) return;
78 sz[x]+=v; lz[x]+=v;
79 }
80
81 void lik(int x,int y) {
82 p[x]=y; access(y); splay(y); add(y,sz[x]);
83 }
84
85 void cut(int x) {
86 access(x); splay(x); add(lc,-sz[x]);
87 p[lc]=0; lc=0;
88 }
89
90 }t;
91
92 struct SAM {
93 int last,rt,tot,ch[N][26],fa[N],l[N],p,np,q,nq;
94
95 void init() {
96 last=rt=tot=1;
97 }
98
99 void insert(int c) {
100 p=last; np=++tot; t.sz[np]=1; last=np;
101 l[np]=l[p]+1;
102 for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
103 if(!p) {
104 fa[np]=rt;
105 t.lik(np,rt);
106 }
107 else {
108 int q=ch[p][c];
109 if(l[q]==l[p]+1) {
110 fa[np]=q;
111 t.lik(np,q);
112 }
113 else {
114 nq=++tot; l[nq]=l[p]+1;
115 memcpy(ch[nq],ch[q],sizeof(ch[q]));
116 fa[nq]=fa[q]; t.lik(nq,fa[q]);
117 fa[q]=fa[np]=nq;
118 t.cut(q); t.lik(q,nq); t.lik(np,nq);
119 for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
120 }
121 }
122 }
123 }sam;
124
125 int main() {
126 read(Q);
127 scanf("%s",s);
128 len=strlen(s);
129 sam.init();
130 for(int i=0;i<len;i++) sam.insert(s[i]-'A');
131 while(Q--) {
132 scanf("%s",op);
133 gets(mask);
134 len=chars.length();
135 if(op[0]=='A') {
136 for(int i=0;i<len;i++)
137 sam.insert(chars[i]-'A');
138 }
139 else {
140 int now=sam.rt;
141 for(int i=0;i<len;i++) {
142 int c=chars[i]-'A';
143 if(!sam.ch[now][c]) {
144 puts("0");
145 break;
146 }
147 now=sam.ch[now][c];
148 if(i==len-1) {
149 t.splay(now);
150 mask^=t.sz[now];
151 printf("%d\n",t.sz[now]);
152 }
153 }
154 }
155 }
156 return 0;
157 }
158 /*
159 7
160 A
161 ADD BAABAC
162 ADD BAAB
163 QUERY BAAB
164 */