您的位置:首页 > 其它

[BZOJ2555]SubString(后缀自动机+lct)

2017-04-04 08:42 375 查看

题目描述

传送门

题解

询问每一个字符串出现过几次,实际上就是将这个字符串在后缀自动机上匹配,然后查询最终匹配到的那个点的right集合的大小

又因为是在线的,pre指针经常会变化,所以把pa树用lct维护一下

维护lct的时候不要维护子树和,而应该连上一个点就将它一直到根的路径上的点都加上这个点的权,断开一个点就减去这个点的权,这样维护一棵有根树

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 3000005

int n,len,ans;
char opt[10],s
;
int f
,ch
[2],size
,delta
,stack
;
int son
[30],pre
,step
,root,last,sz,p,np,q,nq;

//--------------------init----------------------
void init(int mask)
{
int len=strlen(s);
for (int i=0;i<len;++i)
{
mask=(mask*131+i)%len;
char t=s[i];
s[i]=s[mask];
s[mask]=t;
}
}
//--------------------lct-----------------------
bool isroot(int x)
{
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void pushdown(int x)
{
if (x&&delta[x])
{
if (ch[x][0]) size[ch[x][0]]+=delta[x],delta[ch[x][0]]+=delta[x];
if (ch[x][1]) size[ch[x][1]]+=delta[x],delta[ch[x][1]]+=delta[x];
delta[x]=0;
}
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
if (!isroot(old)) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
}
void splay(int x)
{
int top=0;stack[++top]=x;
for (int i=x;!isroot(i);i=f[i]) stack[++top]=f[i];
for (int i=top;i;--i) pushdown(stack[i]);

for (int fa;!isroot(x);rotate(x))
if (!isroot(fa=f[x]))
rotate((get(x)==get(fa))?fa:x);
}
void access(int x)
{
int t=0;
for (;x;t=x,x=f[x])
{
splay(x);
ch[x][1]=t;
}
}
void link(int x,int y)
{
f[y]=x;
access(x);
splay(x);
size[x]+=size[y],delta[x]+=size[y];
}
void cut(int x,int y)
{
access(y);
splay(y);
size[x]-=size[y];delta[x]-=size[y];
ch[y][0]=f[x]=0;
}
int find(int x)
{
access(x);
splay(x);
while (ch[x][0]) x=ch[x][0];
return x;
}
//--------------------sam-----------------------
void extend(int i)
{
int x=s[i]-'A';
p=last;np=++sz;last=np;
step[np]=step[p]+1;
while (p&&!son[p][x])
{
son[p][x]=np;
p=pre[p];
}
if (!p)
{
pre[np]=root;
f[np]=root;
}
else
{
q=son[p][x];
if (step[q]==step[p]+1)
{
pre[np]=q;
f[np]=q;
}
else
{
nq=++sz;
step[nq]=step[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
pre[nq]=pre[q];link(pre[q],nq);
while (son[p][x]==q)
{
son[p][x]=nq;
p=pre[p];
}
cut(pre[q],q);
pre[q]=nq;link(nq,q);
pre[np]=nq;link(nq,np);
}
}
access(np);
splay(np);
++size[np];++delta[np];
}
int sam()
{
p=root;
for (int i=0;i<len;++i)
{
int x=s[i]-'A';
p=son[p][x];
}
if (!p) return 0;
access(p);
splay(p);
return size[p];
}

//--------------------main-----------------------
int main()
{
scanf("%d",&n);
scanf("%s",s);len=strlen(s);
root=last=++sz;
for (int i=0;i<len;++i)
extend(i);
int mask=0;
while (n--)
{
scanf("%s",opt);
scanf("%s",s);len=strlen(s);
init(mask);

if (opt[0]=='A')
{
for (int i=0;i<len;++i)
extend(i);
}
else
{
ans=sam();
printf("%d\n",ans);
mask^=ans;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: