LCT+SAM
求子串出现次数=节点right大小 所以LCT动态维护节点Right集合大小
我s[i]-'A' 写成了 s[i]-'a' wokkkkkkkkkkk
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
//by zfy =.=
const int N=1200005;
char s[3005000];
int Len,Q,mask;
void Get(int mask){
scanf("%s",s);Len=strlen(s);
for(int j=0;j<Len;j++){
mask=(mask*131+j)%Len;
swap(s[j],s[mask]);
}
}
struct LCT{
int tr[N][2],fa[N],tag[N],w[N],q[N],top;
bool isroot(int x){
return tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x;
}
void zig(int x){
int y=fa[x];
tr[y][0]=tr[x][1];if(tr[x][1]) fa[tr[x][1]]=y;tr[x][1]=y;
if(tr[fa[y]][0]==y) tr[fa[y]][0]=x;
if(tr[fa[y]][1]==y) tr[fa[y]][1]=x;
fa[x]=fa[y];fa[y]=x;
}
void zag(int x){
int y=fa[x];
tr[y][1]=tr[x][0];if(tr[x][0]) fa[tr[x][0]]=y;tr[x][0]=y;
if(tr[fa[y]][0]==y) tr[fa[y]][0]=x;
if(tr[fa[y]][1]==y) tr[fa[y]][1]=x;
fa[x]=fa[y];fa[y]=x;
}
void splay(int x){q[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
while(top) down(q[top--]);
while(!isroot(x)){
int y=fa[x];
if(isroot(y)) {
if(tr[y][0]==x) zig(x);
else zag(x);
}
else {
if(tr[fa[y]][0]==y) {
if(tr[y][0]==x){
zig(y);zig(x);
}else {
zag(x);zig(x);
}
}
else {
if(tr[y][1]==x){
zag(y);zag(x);
}else {
zig(x);zag(x);
}
}
}
}
}
void access(int x){
for(int t=0;x;t=x,x=fa[x]){
splay(x);tr[x][1]=t;
}
}
void down(int x){
add(tr[x][0],tag[x]);
add(tr[x][1],tag[x]);
tag[x]=0;
}
void add(int x,int ww){
if(!x) return;
tag[x]+=ww;w[x]+=ww;
}
void link(int x,int y){
fa[x]=y;access(y);splay(y);add(y,w[x]);
}
void cut(int x){
access(x);splay(x);add(tr[x][0],-w[x]);
fa[tr[x][0]]=0;tr[x][0]=0;
}
}T;
struct SAM{
int p,np,q,nq,l[N],tr[N][26],fa[N],cnt,last;
SAM(){
last=++cnt;
}
void add(int x){
p=last;np=last=++cnt;T.w[np]=1;l[np]=l[p]+1;
for(;p&&!tr[p][x];p=fa[p]) tr[p][x]=np;
if(!p) {fa[np]=1;T.link(np,1);}
else {
q=tr[p][x];
if(l[q]==l[p]+1) {fa[np]=q;T.link(np,q);}
else {
nq=++cnt;l[nq]=l[p]+1;
memcpy(tr[nq],tr[q],sizeof tr[q]);
fa[nq]=fa[q];T.link(nq,fa[q]);
T.cut(q);fa[q]=fa[np]=nq;
T.link(q,nq);T.link(np,nq);
for(;tr[p][x]==q;p=fa[p]) tr[p][x]=nq;
}
}
}
void build(){
scanf("%s",s);Len=strlen(s);
for(int i=0;i<Len;i++) add(s[i]-'A');
}
void add(){
Get(mask);for(int i=0;i<Len;i++) add(s[i]-'A');
}
int ask(){
Get(mask);int cur=1;
for(int i=0;i<Len;i++){
if(tr[cur][s[i]-'A']) cur=tr[cur][s[i]-'A'];
else return 0;
}
T.splay(cur);
return T.w[cur];
}
}S;
int main(){
scanf("%d",&Q);S.build();
for(int i=1;i<=Q;i++){
scanf("%s",s);
if(s[0]=='A') S.add();
else {
int res=S.ask();
printf("%d\n",res);
mask^=res;
}
}
return 0;
}
/*
4
A
QUERY A
ADD BBABBBBAAB
QUERY A
QUERY B
*/