BZOJ2555 Substring
传送门
样例毒瘤 强制在线毒瘤(
做法比较显然啦 我们需要维护一个SAM 并资磁查询子树大小
由于强制在线 所以就需要LCT咯
查询子树大小我们可以变成链加+单点查询
然后匹配过程就和ACA的跳跳跳一样啦
decode这个地方真的坑 mask要设局部变量
附代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define fa(x) t[x].fa
#define not_root(x) (ls(fa(x))==x||rs(fa(x))==x)
#define inf 20021225
#define ll long long
#define mxn 600000
using namespace std;
struct node{int fa,son[26],val,tag;};
struct tree
{
node t[mxn*4];
void pushdown(int x)
{
if(!x) return;
if(t[x].tag)
{
int tag=t[x].tag;
if(ls(x)) t[ls(x)].val+=tag,t[ls(x)].tag+=tag;
if(rs(x)) t[rs(x)].val+=tag,t[rs(x)].tag+=tag;
t[x].tag=0;
}
}
void pushup(int x)
{
if(!x) return;
t[x].val=t[ls(x)].val+t[rs(x)].val;
}
void rotate(int x)
{
if(!not_root(x)||!x) return;
int f=fa(x),gf=fa(f);
int k=rs(f)==x,p=k^1;
if(not_root(f)) t[gf].son[rs(gf)==f]=x;
t[x].fa=gf;t[f].fa=x;
if(t[x].son[p]) t[t[x].son[p]].fa=f;
t[f].son[k]=t[x].son[p];
t[x].son[p]=f;
}
void push(int x)
{
if(not_root(x)) push(fa(x));
pushdown(x);
}
void splay(int x)
{
push(x);
while(not_root(x))
{
int f=t[x].fa,gf=t[f].fa;
if(not_root(f))
(rs(f)==x)^(rs(gf)==f)?rotate(x):rotate(f);
rotate(x);
}
}
void access(int x)
{
int y=0;
do
{
splay(x);
t[x].son[1]=y;
y=x;x=t[x].fa;
}while(x);
}
void link(int x,int y) // link x to y
{
t[x].fa=y; access(y); splay(y); t[y].tag+=t[x].val; t[y].val+=t[x].val;
}
void cut(int x)// cut x
{
access(x); splay(x);
t[ls(x)].tag-=t[x].val; t[ls(x)].val-=t[x].val;
t[ls(x)].fa=0; t[x].son[0]=0;
}
}lct;
struct point{int len,fa,ch[2];};
struct sam
{
point pt[mxn*4];
int rt,poi,lt;
void insert(int c)
{
int p=lt,np=lt=++poi; pt[np].len=pt[p].len+1;
lct.t[np].val=1;
for(; p&& !pt[p].ch[c];p=pt[p].fa) pt[p].ch[c]=np;
if(!p){lct.link(np,rt);pt[np].fa=rt;return;}
int q=pt[p].ch[c];
if(pt[q].len==pt[p].len+1){lct.link(np,q);pt[np].fa=q;return;}
int nq=++poi; pt[nq].len=pt[p].len+1;
memcpy(pt[nq].ch,pt[q].ch,sizeof(pt[q].ch));
lct.cut(q); pt[nq].fa=pt[q].fa; lct.link(nq,pt[q].fa);
pt[q].fa=pt[np].fa=nq; lct.link(q,nq); lct.link(np,nq);
for(;p&&pt[p].ch[c]==q;p=pt[p].fa) pt[p].ch[c]=nq;
}
void init()
{
rt=lt=++poi;
}
void build(char s[])
{int n=strlen(s);
for(int i=0;i<n;i++) insert(s[i]-'A');
}
int getans(char s[])
{
int pos=rt;int n=strlen(s);
for(int i=0;i<n;i++)
{
if(pt[pos].ch[s[i]-'A']) pos=pt[pos].ch[s[i]-'A'];
else return 0;
}
//printf("QAQ");
lct.access(pos); lct.splay(pos); return lct.t[pos].val;
}
}sam;
char s[mxn];
void decodewithMask(int mask)
{
int n=strlen(s);
for(int i=0;i<n;i++)
{
mask=(mask*131+i)%n;
swap(s[i],s[mask]);
}
}
char cz[10];
int main()
{
int q,mask=0,ans=0;
//freopen("2.in","r",stdin);
scanf("%d",&q);
scanf("%s",s);sam.init();sam.build(s);
for(int i=0;i<q;i++)
{
scanf("%s",cz);
scanf("%s",s);
decodewithMask(mask);
if(cz[0]=='A') sam.build(s);
else ans=sam.getans(s),printf("%d\n",ans),mask^=ans;
}
return 0;
}
/**
2
AB
ADD BBABB
QUERY BB
*/