题意
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
题解
直接SAM
然后考虑到不断地加边删边,容易想到用LCT来维护parent树
然后每一次就相当于是把这个点到根路径上全部点都加上或减去某个值
lazy标记打一打就好了
还是挺好写的
但是由于我还是太SB了。。所以还是调了挺久
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int N=600005*2;
int T;
int len,tot,last;
struct qq
{
int par,son[26],step;
}s[N];//SAM
struct qr
{
int c,fa,rev,son[2],lzy;//这个节点的值 父亲 区间加
void bt (int x)
{
son[0]=son[1]=fa=rev=lzy=0;
c=x;
};
}tr[N];//LCT
void add (int x,int y){tr[x].lzy+=y;}
bool is_root (int x)
{
int fa=tr[x].fa;
if (tr[fa].son[0]==x) return false;
if (tr[fa].son[1]==x) return false;
return true;
}
void push_down (int x)
{
int s1=tr[x].son[0],s2=tr[x].son[1];
if (tr[x].rev)
{
swap(tr[x].son[0],tr[x].son[1]);
if (s1!=0)tr[s1].rev^=1;
if (s2!=0)tr[s2].rev^=1;
tr[x].rev^=1;
}
if (tr[x].lzy!=0)
{
tr[x].c+=tr[x].lzy;
if (s1!=0) add(s1,tr[x].lzy);
if (s2!=0) add(s2,tr[x].lzy);
tr[x].lzy=0;
}
}
void pre (int x)
{
if (!is_root(x)) pre(tr[x].fa);
push_down(x);
}
void rotate (int x)
{
int y=tr[x].fa,z=tr[y].fa,r,R;
int w=(tr[y].son[0]==x);
r=tr[x].son[w];R=y;
tr[R].son[1-w]=r;
if (r!=0) tr[r].fa=R;
r=x;R=z;
if (!is_root(y))
{
if (tr[R].son[0]==y) tr[R].son[0]=r;
else tr[R].son[1]=r;
}
tr[r].fa=R;
r=y;R=x;
tr[R].son[w]=r;
tr[r].fa=R;
}
void splay (int x)
{
pre(x);
while (!is_root(x))
{
int y=tr[x].fa,z=tr[y].fa;
if (!is_root(y))
{
if ((tr[z].son[0]==y)==(tr[y].son[0]==x)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
void access (int x)
{
int Last=0;
while (x!=0)
{
splay(x);
tr[x].son[1]=Last;
Last=x;
x=tr[x].fa;
}
}
void link (int x,int y)//x向y连边
{
tr[y].fa=x;
access(x);
splay(x);
add(x,tr[y].c);
}
void cut (int x)
{
access(x);
splay(x);
add(tr[x].son[0],-tr[x].c);
tr[x].son[0]=tr[tr[x].son[0]].fa=0;
}
void ins (int x)
{
int np=++tot,p=last;
s[np].step=s[p].step+1;tr[np].bt(1);
while (p!=0&&s[p].son[x]==0) s[p].son[x]=np,p=s[p].par;
if (p==0) {s[np].par=1;link(1,np);}
else
{
int q=s[p].son[x];
if (s[q].step==s[p].step+1) s[np].par=q,link(q,np);
else
{
int nq=++tot;tr[nq].bt(0);
s[nq]=s[q];
link(s[nq].par,nq);
s[nq].step=s[p].step+1;
cut(q);
link(nq,q);link(nq,np);
s[q].par=s[np].par=nq;
while (p!=0&&s[p].son[x]==q) s[p].son[x]=nq,p=s[p].par;
}
}
last=np;
}
char ss[N];
int main()
{
last=tot=1;
scanf("%d",&T);
scanf("%s",ss);len=strlen(ss);
for (int u=0;u<len;u++) ins(ss[u]-'A');
int mask=0;
while (T--)
{
char SS[10];
scanf("%s %s",SS,ss);
len=strlen(ss);
int tmp=mask;
for (int u=0;u<len;u++)
{
tmp=(tmp*131+u)%len;
swap(ss[tmp],ss[u]);
}
if (SS[0]=='A')
for (int u=0;u<len;u++) ins(ss[u]-'A');
else
{
int x=1;
bool tf=false;
for (int u=0;u<len;u++)
{
int c=ss[u]-'A';
if (s[x].son[c]==0) {printf("0\n");tf=true;break;}
x=s[x].son[c];
}
if (!tf)
{
splay(x);
printf("%d\n",tr[x].c);
mask^=tr[x].c;
}
}
}
return 0;
}