SubString
题目描述
http://www.lydsy.com/JudgeOnline/problem.php?id=2555
题解
这题等价于求sam上每个点的right集合大小。
每插入一个字符串,他的parent-tree上的所有父亲节点的right集合都要加1。
直接暴力加显然会TLE,所以我们可以用lct来维护parent-tree。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define N 1200010
#define M 3000010
using namespace std;
int Q,n,cnt=1,mask,ans,ch[N][30],fa[N],top[N],f[N];
char s[M],str[10];
struct node{int c[2],fa,size,tag;}t[N];
class lct
{
void add(int x,int y)
{
t[x].size+=y;t[x].tag+=y;
}
void pushdown(int x)
{
if(!t[x].tag)return;
int lc=t[x].c[0],rc=t[x].c[1];
add(lc,t[x].tag);add(rc,t[x].tag);
t[x].tag=0;
}
void rotate(int x,int k)
{
int y=t[x].fa,f=(t[t[y].fa].c[1]==y);
pushdown(y);pushdown(x);
if(!t[y].fa)fa[x]=fa[y];
t[x].fa=t[y].fa;t[t[y].fa].c[f]=x;
t[y].c[k]=t[x].c[k^1];t[t[y].c[k]].fa=y;
t[y].fa=x;t[x].c[k^1]=y;
}
public:
void splay(int x)
{
pushdown(x);
while(t[x].fa)
{
int y=t[x].fa,f=(t[y].c[1]==x);
if(!t[y].fa)rotate(x,f);
else
{
if((t[t[y].fa].c[1]==y)==f)
rotate(y,f),rotate(x,f);
else rotate(x,f),rotate(x,f^1);
}
}
}
void access(int x)
{
for(int y=0;x;y=x,x=fa[x])
{
splay(x);
t[t[x].c[1]].fa=0;fa[t[x].c[1]]=x;
t[x].c[1]=y;fa[y]=0;t[y].fa=x;
}
}
void link(int x,int y)
{
access(y);splay(y);fa[x]=y;add(y,t[x].size);
}
void cut(int x)
{
access(x);splay(x);
add(t[x].c[0],-t[x].size);
t[t[x].c[0]].fa=0;
fa[t[x].c[0]]=fa[x];
t[x].c[0]=fa[x]=0;
}
}T;
class sam
{
public:
int insert(int x,int c)
{
int nx=++cnt;f[nx]=f[x]+1;t[nx].size=1;
while(x&&!ch[x][c])ch[x][c]=nx,x=top[x];
if(!x)top[nx]=1,T.link(nx,1);
else
{
int p=ch[x][c];
if(f[p]==f[x]+1)top[nx]=p,T.link(nx,p);
else
{
int np=++cnt;f[np]=f[x]+1;
memcpy(ch[np],ch[p],sizeof(ch[p]));
top[np]=top[p];T.link(np,top[p]);
top[nx]=top[p]=np;T.cut(p);
T.link(p,np);T.link(nx,np);
while(x&&ch[x][c]==p)ch[x][c]=np,x=top[x];
}
}
return nx;
}
int qry(char *s,int len)
{
int x=1;
for(int i=0;i<len;i++)
{
s[i]-='A';
if(!ch[x][s[i]])return 0;
x=ch[x][s[i]];
}
T.access(x);T.splay(x);
return t[x].size;
}
}S;
void get(int len,int mask)
{
for(int i=0;i<len;i++)
{
mask=(mask*131+i)%len;
swap(s[i],s[mask]);
}
}
int main()
{
int pos=1,sum=0;
scanf("%d %s",&Q,s);n=strlen(s);
for(int i=0;i<n;i++)
pos=S.insert(pos,s[i]-'A');
while(Q--)
{
scanf(" %s %s",str,s);
int len=strlen(s);get(len,mask);
if(str[0]=='A')
{
for(int i=0;i<len;i++)
pos=S.insert(pos,s[i]-'A');
}
else printf("%d\n",ans=S.qry(s,len)),mask^=ans;
}
return 0;
}