考虑在extend($x$)的时候维护SAM中所有串出现的次数,存在每个节点上
在$S$的尾部加入一个字符$x$,只有($S$的后缀+$x$)这种串会多出现一次,所以extend完之后把$np$在parent树中的所有祖先答案$+1$
在extend的过程中只有常数次切换$parent$,相应维护即可
我们要维护parent树,支持link,cut,链增值,点查询,写个lct就好了
糟心...xsy上就是过不了
不要以为仅访问节点信息就可以只pushdown不splay,因为splay的复杂度就是靠splay这个操作保证的
我错了我一定每次访问都splay
#include<stdio.h>
#include<string.h>
#define N 1200010
struct lct{
int fa[N],ch[N][2],v[N],d[N],stk[N];
#define ls ch[x][0]
#define rs ch[x][1]
void ad(int x,int f){
v[x]+=f;
d[x]+=f;
}
void pushdown(int x){
if(d[x]){
if(ls)ad(ls,d[x]);
if(rs)ad(rs,d[x]);
d[x]=0;
}
}
void rot(int x){
int y,z,f,b;
y=fa[x];
z=fa[y];
f=(ch[y][0]==x);
b=ch[x][f];
fa[x]=z;
fa[y]=x;
if(b)fa[b]=y;
ch[x][f]=y;
ch[y][f^1]=b;
if(ch[z][0]==y)ch[z][0]=x;
if(ch[z][1]==y)ch[z][1]=x;
}
bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void gao(int x){
int t=0;
while(!isrt(x)){
t++;
stk[t]=x;
x=fa[x];
}
t++;
stk[t]=x;
for(;t;t--)pushdown(stk[t]);
}
void splay(int x){
int y,z;
gao(x);
while(!isrt(x)){
y=fa[x];
z=fa[y];
if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
rot(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
rs=y;
y=x;
x=fa[x];
}
}
void add(int y,int f){
access(y);
splay(y);
ad(y,f);
}
void link(int x,int y){
if(x==0||y==0)return;
fa[x]=y;
add(y,v[x]);
}
void cut(int x){
access(x);
splay(x);
ad(ls,-v[x]);
fa[ls]=0;
ls=0;
}
}l;
struct sam{
int ch[26],fa,v;
}t[N];
int M=1,las=1;
void extend(int c){
int p=las,np=++M,q,nq;
t[np].v=t[p].v+1;
while(p&&t[p].ch[c]==0){
t[p].ch[c]=np;
p=t[p].fa;
}
if(p==0){
t[np].fa=1;
l.link(np,1);
}else{
q=t[p].ch[c];
if(t[q].v==t[p].v+1){
t[np].fa=q;
l.link(np,q);
}else{
nq=++M;
t[nq]=t[q];
l.link(nq,t[q].fa);
t[nq].v=t[p].v+1;
l.cut(q);
t[np].fa=t[q].fa=nq;
l.link(q,nq);
l.link(np,nq);
while(p&&t[p].ch[c]==q){
t[p].ch[c]=nq;
p=t[p].fa;
}
}
}
las=np;
l.add(np,1);
}
char s[N];
void decode(int mask){
int i,n;
char c;
n=strlen(s);
for(i=0;i<n;i++){
mask=(mask*131+i)%n;
c=s[i];
s[i]=s[mask];
s[mask]=c;
}
}
void insert(){
for(int i=0;s[i];i++)extend(s[i]-'A');
}
int query(){
int i,p;
for(i=0,p=1;s[i];i++){
s[i]-='A';
if(t[p].ch[s[i]]==0)return 0;
p=t[p].ch[s[i]];
}
l.splay(p);
return l.v[p];
}
int main(){
int m,res,mask=0;
char ch[10];
scanf("%d%s",&m,s);
insert();
while(m--){
scanf("%s%s",ch,s);
decode(mask);
if(ch[0]=='A')
insert();
else{
res=query();
printf("%d\n",res);
mask^=res;
}
}
}