题意:给一个串,支持
1.询问一个串在当前串中的出现次数
2.在串尾加一个字符串
强制在线
Sol:
如果没有添加操作,答案就是将给定串在SAM上跑到的最终状态的Right集合大小(到不了就是0)
Right集合大小可用Parent树算
现在有了添加,Parent树是会变化(加边或删边)
容易想到可用LCT维护Parent树形态
每个点影响的范围是她到根的一条链,影响是链上加自己的权值
代码题QAQ
Hint:字符集大小其实是2 , 解密函数中mask是局部变量,不会修改全局的mask
Code:
#include<bits/stdc++.h>
#define debug(x) cout<<#x<<"="<<x<<endl
#define PAD(x,y) memset(x,y,sizeof x)
#define CPY(x,y) memcpy(x,y,sizeof x)
using namespace std;
const int maxn = 600009, alpha = 2;
int tot,root,last;
struct state
{
int son[alpha];
int mx,siz,par;
}node[maxn<<1];
int son[maxn<<1][2],fa[maxn<<1],val[maxn<<1],tag[maxn<<1],S[maxn<<1];
bool rev[maxn<<1];
char str[3000009],opt[100];
int m,mask;
void init(){tot=last=root=1;}
void decode(char *s)
{
int len=strlen(s),tmp=mask;
for(int i=0;i<len;i++)
{
tmp=(tmp*131+i)%len;
swap(s[i],s[tmp]);
}
}
inline bool is_root(int x){return (son[fa[x]][0]!=x)&&(son[fa[x]][1]!=x);}
void down(int x)
{
if(tag[x])
{
tag[son[x][0]]+=tag[x];val[son[x][0]]+=tag[x];
tag[son[x][1]]+=tag[x];val[son[x][1]]+=tag[x];
tag[x]=0;
}
if(rev[x])
{
rev[son[x][0]]^=1;
rev[son[x][1]]^=1;
swap(son[x][0],son[x][1]);
rev[x]=0;
}
}
void make_plus(int x,int y){val[x]+=y;tag[x]+=y;}
void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if(son[y][0]==x) l=0;else l=1;r=l^1;
if(!is_root(y)) if(son[z][0]==y) son[z][0]=x;
else son[z][1]=x;
fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
son[y][l]=son[x][r];son[x][r]=y;
}
void splay(int x)
{
int y=x,z,top=0;
while(!is_root(y)) S[++top]=y,y=fa[y];S[++top]=y;
while(top) down(S[top]),top--;
while(!is_root(x))
{
y=fa[x];z=fa[y];
if(!is_root(y)) if((son[y][0]==x)^(son[z][0]==y)) rotate(x);
else rotate(y);
rotate(x);
}
}
void access(int x)
{
int t=0;
while(x)
{
splay(x);
son[x][1]=t;
t=x;x=fa[x];
}
}
void make_root(int x)
{
access(x);splay(x);rev[x]^=1;
}
void link(int x,int y)
{
make_root(x);fa[x]=y;
make_root(root);
access(x);splay(x);
make_plus(son[x][0],val[x]);
}
void cut(int x,int y)
{
make_root(root);
access(x);splay(x);
make_plus(son[x][0],-val[x]);
make_root(x);access(y);splay(y);son[y][0]=fa[x]=0;
}
void extend(int x)
{
int p=last,np=++tot;
node[np].mx=node[p].mx+1;
node[np].siz=1;val[np]=1;
while(p&&node[p].son[x]==0)
node[p].son[x]=np,p=node[p].par;
if(p==0) node[np].par=root,link(np,root);
else
{
int q=node[p].son[x];
if(node[p].mx+1==node[q].mx) node[np].par=q,link(np,q);
else
{
int nq=++tot;
node[nq].mx=node[p].mx+1;
node[nq].par=node[q].par,link(nq,node[q].par);
cut(q,node[q].par),node[q].par=nq,link(q,nq);
node[np].par=nq,link(np,nq);
CPY(node[nq].son,node[q].son);
while(p&&node[p].son[x]==q)
node[p].son[x]=nq,p=node[p].par;
}
}
last=np;
}
void solve(char *str)
{
int now=root;
for(int i=0;str[i];i++)
if(node[now].son[str[i]-'A']) now=node[now].son[str[i]-'A'];
else{puts("0");return;}
splay(now);printf("%d\n",val[now]);mask^=val[now];
}
int main()
{
scanf("%d%s",&m,str+1);
init();
for(int i=1;str[i];i++)
extend(str[i]-'A');
while(m--)
{
scanf("%s%s",opt+1,str);
decode(str);
if(opt[1]=='Q') solve(str);
else for(int i=0;str[i];i++) extend(str[i]-'A');
}
return 0;
}