题面:https://www.lydsy.com/JudgeOnline/problem.php?id=2555
题解:
如果没有修改操作,这就是一道SAM模板题。
有了修改操作后,发现fail树可能会有断边的过程,
不难想到使用LCT维护fail树。
每次加边时,需要将贡献也一并加入LCT的节点中,
查询时,找到对应节点,将其splay到根,此时的val就是答案。
注意:
1.splay时记得要pushdown;
2.是大写字母;
3.数组要开到(1.2e6)。
时间复杂度:(O(n+Qlogn))
代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
char c[3030000];
int n,m,Q;
namespace LCT{
int fa[1202000],ch[1202000][2],laz[1202000],w[1202000];
int st[1202000];
IN nroot(int x){
return (ch[fa[x]][0]==x)||(ch[fa[x]][1]==x);
}
IN get(int x){
return ch[fa[x]][1]==x;
}
I add(int x,int val){
if(!x)return;laz[x]+=val;w[x]+=val;
}
I push_down(int x){
add(ch[x][0],laz[x]);add(ch[x][1],laz[x]);
laz[x]=0;
}
I rotate(int x){
re y=fa[x],z=fa[y],dir=get(x);
if(nroot(y))ch[z][get(y)]=x;fa[x]=z;
ch[y][dir]=ch[x][dir^1];fa[ch[x][dir^1]]=y;
ch[x][dir^1]=y;fa[y]=x;
}
I splay(int x){
re y=x,z=0;st[++z]=y;
while(y)st[++z]=y=fa[y];
while(z)push_down(st[z--]);
while(nroot(x)){
y=fa[x],z=fa[y];
if(nroot(y))rotate((get(x)^get(y))?x:y);
rotate(x);
}
}
I access(int x){
for(re y=0;x;x=fa[y=x])splay(x),ch[x][1]=y;
}
I link(int x,int y){
fa[x]=y;access(y);splay(y);add(y,w[x]);
}
I cut(int x,int y){
access(x);splay(x);add(ch[x][0],-w[x]);
fa[ch[x][0]]=0;ch[x][0]=0;
}
};
namespace SAM{
int len[1202000],ch[1202000][27],link[1202000],tot,las,p,q,cle,cur;
I init(){tot=las=1;}
I add(int x){
cur=++tot;len[cur]=len[las]+1;p=las;las=cur;LCT::w[cur]=1;
while(p&&!ch[p][x])ch[p][x]=cur,p=link[p];
if(!p){link[cur]=1;LCT::link(cur,1);return;}
q=ch[p][x];
if(len[p]+1==len[q]){link[cur]=q;LCT::link(cur,q);return;}
cle=++tot;len[cle]=len[p]+1,link[cle]=link[q];LCT::link(cle,link[cle]);
memcpy(ch[cle],ch[q],sizeof(ch[q]));
LCT::cut(q,link[q]);link[q]=cle;LCT::link(q,link[q]);link[cur]=cle;LCT::link(cur,cle);
while(p&&ch[p][x]==q)ch[p][x]=cle,p=link[p];
}
I insert(){F(i,0,n-1)add(c[i]-'A'+1);}
I ques(){
p=1;
F(i,0,n-1){
if(!ch[p][c[i]-'A'+1]){
printf("0
");return;
}
p=ch[p][c[i]-'A'+1];
}
LCT::splay(p);
printf("%d
",LCT::w[p]);m^=LCT::w[p];
}
};
I getit(int x){
scanf("%s",c);n=strlen(c);
F(i,0,n-1){
x=(x*131+i)%n;
swap(c[i],c[x]);
}
}
int main(){
read(Q);m=0;
scanf("%s",c);
n=strlen(c);
SAM::init();
SAM::insert();
while(Q--){
scanf("%s",c+1);
if(c[1]=='A'){
getit(m);SAM::insert();
}
else{
getit(m);SAM::ques();
}
}
return 0;
}