构建出后缀自动机后在自动机上找到
str
在
fail
指针构成的树中的位置,子树大小就是答案。
我们可以用LCT维护后缀自动机,添加字符时链上修改就可以了。
时间复杂度
O(|S|log|S|)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 1200010
int i,j,k,n,m,Num,f[N],Next[N][26],Pre[N],mask,ch[N][2],Len[N],p[N],a[N],Q,Ans,Last=1,M;
char S[N<<2];
bool b[N],r[N];
inline bool Get(int x){
return ch[f[x]][1]==x;
}
inline void Rev(int x){
swap(ch[x][0],ch[x][1]);
r[x]^=1;
}
inline void Add(int x,int y){
a[x]+=y;
p[x]+=y;
}
inline void Down(int x){
if(r[x]){
Rev(ch[x][0]);
Rev(ch[x][1]);
r[x]=0;
}
if(p[x]){
Add(ch[x][0],p[x]);
Add(ch[x][1],p[x]);
p[x]=0;
}
}
inline void Rotate(int x){
bool d=Get(x);int y=f[x];
if(b[y])b[x]=1,b[y]=0;else ch[f[y]][Get(y)]=x;
ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
f[x]=f[y];f[y]=x;ch[x][d^1]=y;
}
inline void P(int x){
if(!b[x])P(f[x]);
Down(x);
}
inline void Splay(int x){
for(P(x);!b[x];Rotate(x))
if(!b[f[x]])Rotate(Get(x)==Get(f[x])?f[x]:x);
}
inline void Access(int x){
int y=0;
while(x){
Splay(x);
b[ch[x][1]]=1;ch[x][1]=y;b[y]=0;
y=x;x=f[x];
}
}
inline void mr(int x){
Access(x);Splay(x);Rev(x);
}
inline void Link(int x,int y){
mr(x);f[x]=y;
}
inline void Cut(int x,int y){
mr(x);Access(y);Splay(y);
ch[y][0]=f[x]=0;b[x]=1;
}
inline void Extend(int ch){
int p,x=++Num;
b[x]=1;
Len[x]=Len[Last]+1;
for(p=Last;p&&!Next[p][ch];p=Pre[p])Next[p][ch]=x;
if(!p)Pre[x]=1,Link(x,1);else{
int q=Next[p][ch];
if(Len[p]+1==Len[q])Pre[x]=q,Link(x,q);else{
int C=++Num;b[C]=1;
Len[C]=Len[p]+1;Pre[C]=Pre[q];Link(C,Pre[q]);
memcpy(Next[C],Next[q],sizeof(Next[q]));
Pre[q]=Pre[x]=C;Cut(q,Pre[q]);Link(q,C);Link(x,C);
P(q);a[C]=a[q];
for(;p&&Next[p][ch]==q;p=Pre[p])Next[p][ch]=C;
}
}
Last=x;mr(1);Access(x);Splay(x);Add(x,1);
}
inline int Query(){
int p=1;
for(int i=0;i<n;i++)p=Next[p][S[i]-'A'];
if(!p)return 0;
Splay(p);
return a[p];
}
int main(){
scanf("%d",&Q);
scanf("%s",S+1);
n=strlen(S+1);
for(Num=i=b[1]=1;i<=n;i++)Extend(S[i]-'A');
while(Q--){
scanf("%s",S);
if(S[0]=='Q'){
scanf("%s",S);n=strlen(S);
for(mask=M,i=0;i<n;i++){
mask=(mask*131+i)%n;
swap(S[mask],S[i]);
}
Ans=Query();
printf("%d\n",Ans);
M^=Ans;
}else{
scanf("%s",S);n=strlen(S);
for(mask=M,i=0;i<n;i++){
mask=(mask*131+i)%n;
swap(S[mask],S[i]);
}
for(i=0;i<n;i++)Extend(S[i]-'A');
}
}
return 0;
}