bzoj2555 SubString
题意:两个操作:在原来的字符串后面加上一个新的字符串;查询一个字符串出现了几次
方法:假如没有假如新字符串的要求,就是模板了。
那么考虑加上新字符串会有什么影响,假如新的字符串以后,有的fa就会改变,而其他的是不会变的。
因此考虑LCT维护。每次连边,
link(p,fa[p])
l
i
n
k
(
p
,
f
a
[
p
]
)
,那么fa[p]到根的size就会加上
size[p]
s
i
z
e
[
p
]
。
删边(更改fa),
cut(p)
c
u
t
(
p
)
,也就是把p和它的fa断开,那么fa[p]到根也就要减去
size[p]
s
i
z
e
[
p
]
也就是路径加、单点查询(就不需要update了…….)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 600010
char str[N],op[10];
int last=0,root,cnt=0,Q,mask=0,mx[N<<1],fa[N<<1],son[N<<1][26],size[N<<1],tag[N<<1],Fa[N<<1],ch[N<<1][2];
inline void add(int x,int y){
tag[x]+=y;size[x]+=y;
}
inline bool isroot(int x){return x!=ch[Fa[x]][0] && x!=ch[Fa[x]][1];}
inline void rotate(int x){
int y=Fa[x],z=Fa[y],t=ch[y][0]==x;
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
Fa[y]=x;Fa[x]=z;Fa[ch[x][t]]=y;
ch[y][t^1]=ch[x][t];ch[x][t]=y;
}
inline void pushdown(int x){
if(!tag[x]) return;int l=ch[x][0],r=ch[x][1];
size[l]+=tag[x];size[r]+=tag[x];
tag[l]+=tag[x];tag[r]+=tag[x];
tag[x]=0;
}
void push(int x){
if(!isroot(x)) push(Fa[x]);
pushdown(x);
}
inline void splay(int x){
push(x);
while(!isroot(x)){
int y=Fa[x];
if(isroot(y)){rotate(x);return;}
if(ch[y][0]==x^ch[Fa[y]][0]==y) rotate(x);
else rotate(y);rotate(x);
}
}
inline void access(int x){
int y=0;
while(x){
splay(x);ch[x][1]=y;
y=x;x=Fa[x];
}
}
inline void link(int x,int y){
Fa[x]=y;
access(y),splay(y);add(y,size[x]);
}
inline void cut(int x){
access(x);splay(x);add(ch[x][0],-size[x]);
Fa[ch[x][0]]=0;ch[x][0]=0;
}
inline void ins(int ch){
int p=last,np=++cnt;last=np;mx[np]=mx[p]+1;size[np]=1;
while(p && !son[p][ch]) son[p][ch]=np,p=fa[p];
if(!p) fa[np]=root,link(np,root);
else{
int q=son[p][ch];
if(mx[q]==mx[p]+1) fa[np]=q,link(np,q);
else{
int nq=++cnt;mx[nq]=mx[p]+1;
memcpy(son[nq],son[q],sizeof(son[nq]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
cut(q);link(nq,fa[nq]);link(q,nq);link(np,nq);
while(son[p][ch]==q) son[p][ch]=nq,p=fa[p];
}
}
}
int main(){
scanf("%d%s",&Q,str+1);
int n=strlen(str+1);last=root=++cnt;
for(int i=1;i<=n;i++) ins(str[i]-'A');
while(Q--){
scanf("%s%s",op,str+1);n=strlen(str+1);int mask1=mask;
for(int i=1;i<=n;i++) mask1=(mask1*131+i-1)%n,swap(str[i],str[mask1+1]);
if(op[0]=='A') for(int i=1;i<=n;i++) ins(str[i]-'A');
else{
int p=root,f=1;
for(int i=1;i<=n;i++){
if(!son[p][str[i]-'A']){puts("0");f=0;break;}
else p=son[p][str[i]-'A'];
}if(f){splay(p);printf("%d\n",size[p]);mask^=size[p];}
}
}
return 0;
}