【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)
题面
题解
这题看起来不难
每次要求的就是\(right/endpos\)集合的大小
所以搞一个\(LCT\)维护一下\(SAM\)的\(Parent\)树就好了
但是代码一点都不好写(我还是对着黄学长的调的。。。)
于是乎我也学着魔改了一下\(LCT\)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 600006
char ch[MAX];
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int mask,ans;
struct LCT
{
#define lson (t[x].ch[0])
#define rson (t[x].ch[1])
struct Node
{
int ch[2],ff;
int rev,v,ly;
}t[MAX<<1];
int S[MAX<<1],top;
bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
}
void putrev(int x){swap(lson,rson);t[x].rev^=1;}
void putly(int x,int v){t[x].v+=v;t[x].ly+=v;}
void pushdown(int x)
{
if(t[x].rev)
{
if(lson)putrev(lson);
if(rson)putrev(rson);
t[x].rev^=1;
}
if(t[x].ly!=0)
{
if(lson)putly(lson,t[x].ly);
if(rson)putly(rson,t[x].ly);
t[x].ly=0;
}
}
void Splay(int x)
{
S[top=1]=x;
for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
while(top)pushdown(S[top--]);
while(!isroot(x))
{
int y=t[x].ff,z=t[y].ff;
if(!isroot(y))
(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),rson=y;}
void makeroot(int x){access(x);Splay(x);putrev(x);}
void split(int x,int y){makeroot(x);access(y);Splay(y);}
void cut(int x){access(x);Splay(x);putly(lson,-t[x].v);t[lson].ff=0;lson=0;}
void link(int x,int f){t[x].ff=f;access(f);Splay(f);putly(f,t[x].v);}
int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;}
}LCT;
struct SAM
{
struct Node
{
int son[26];
int ff,len;
}t[MAX<<1];
int last,tot;
void init(){last=tot=1;}
void extend(int c)
{
int p=last,np=++tot;last=np;LCT.t[np].v=1;
while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
if(!p)t[np].ff=1,LCT.link(np,1);
else
{
int q=t[p].son[c];
if(t[q].len==t[p].len+1)t[np].ff=q,LCT.link(np,q);
else
{
int nq=++tot;
t[nq]=t[q];
t[nq].len=t[p].len+1;
LCT.link(nq,t[q].ff);
t[q].ff=t[np].ff=nq;
LCT.cut(q);LCT.link(q,nq);LCT.link(np,nq);
while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
}
}
}
}SAM;
void Decode(char *ch,int mask)
{
int l=strlen(ch);
for(int i=0;i<l;++i)
{
mask=(mask*131+i)%l;
swap(ch[i],ch[mask]);
}
}
int main()
{
int Q=read();
SAM.init();
scanf("%s",ch+1);
for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A');
while(Q--)
{
scanf("%s",ch);
if(ch[0]=='A')
{
scanf("%s",ch+1);
Decode(ch+1,mask);
for(int i=1,l=strlen(ch+1);i<=l;++i)SAM.extend(ch[i]-'A');
}
else
{
scanf("%s",ch+1);
Decode(ch+1,mask);
int now=1;
for(int i=1,l=strlen(ch+1);i<=l;++i)
now=SAM.t[now].son[ch[i]-'A'];
if(!now)printf("%d\n",ans=0);
else
{
LCT.Splay(now);
printf("%d\n",ans=LCT.t[now].v);
}
mask^=ans;
}
}
return 0;
}