bzoj2555: SubString
题意
考虑第一问所求即为该串对应的节点的子树内终止节点的个数,而插入一个字符相当于在新增节点到根节点的链+1,于是用LCT维护。
code:
#include<bits/stdc++.h>
using namespace std;
#define re register
const int maxn=1200010;
int Q,mask,ans;
char s[3000010];
string chars;
void gets(int mask)
{
scanf("%s",s);
chars=s;
for(re int j=0;j<(int)chars.length();j++)
{
mask=(mask*131+j)%chars.length();
char t=chars[j];
chars[j]=chars[mask];
chars[mask]=t;
}
}
struct LCT
{
int top;
int fa[maxn],val[maxn],tag[maxn],sta[maxn];
int ch[maxn][2];
inline int get(int x){return ch[fa[x]][1]==x;}
inline bool checkroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void down(int x)
{
if(!tag[x])return;
re int k=tag[x];tag[x]=0;
if(ch[x][0])val[ch[x][0]]+=k,tag[ch[x][0]]+=k;
if(ch[x][1])val[ch[x][1]]+=k,tag[ch[x][1]]+=k;
}
inline void rotate(int x)
{
re int y=fa[x],z=fa[y],k=get(x),w=ch[x][k^1];
if(!checkroot(y))ch[z][get(y)]=x;ch[x][k^1]=y;ch[y][k]=w;
if(w)fa[w]=y;fa[x]=z;fa[y]=x;
}
inline void splay(int x)
{
re int now=x;
sta[top=1]=now;
while(!checkroot(now))sta[++top]=fa[now],now=fa[now];
while(top)down(sta[top--]);
while(!checkroot(x))
{
re int y=fa[x];
if(!checkroot(y))rotate(get(x)==get(y)?y:x);
rotate(x);
}
}
inline void access(int x){for(re int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y;}
inline void link(int x,int y)
{
fa[x]=y;access(y);splay(y);
val[y]+=val[x];tag[y]+=val[x];
}
inline void cut(int x)
{
access(x);splay(x);
val[ch[x][0]]-=val[x],tag[ch[x][0]]-=val[x];
ch[x][0]=fa[ch[x][0]]=0;
}
}tree;
struct SAM
{
int tot,last;
int fa[maxn],len[maxn];
int ch[maxn][30];
SAM(){last=tot=1;}
inline void add(int c)
{
re int now=++tot;len[now]=len[last]+1;tree.val[now]=1;
re int p=last;last=now;
while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
if(!p){fa[now]=1;tree.link(now,1);return;}
re int q=ch[p][c];
if(len[q]==len[p]+1)fa[now]=q,tree.link(now,q);
else
{
re int nowq=++tot;
memcpy(ch[nowq],ch[q],sizeof(ch[q]));
fa[nowq]=fa[q];tree.link(nowq,fa[q]);
tree.cut(q);fa[q]=fa[now]=nowq;tree.link(q,nowq),tree.link(now,nowq);
while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
}
}
inline void build()
{
scanf("%s",s+1);re int len=strlen(s+1);
for(re int i=1;i<=len;i++)add(s[i]-'A');
}
inline void extend()
{
gets(mask);
re int len=chars.size();
for(re int i=0;i<len;i++)add(chars[i]-'A');
}
inline int query()
{
gets(mask);
re int now=1,len=chars.size();
for(re int i=0;i<len;i++)
{
if(!ch[now][chars[i]-'A'])return 0;
now=ch[now][chars[i]-'A'];
}
tree.splay(now);
return tree.val[now];
}
}sam;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d",&Q);
sam.build();
while(Q--)
{
char op[10];scanf("%s",op+1);
if(op[1]=='A')sam.extend();
else printf("%d\n",ans=sam.query()),mask^=ans;
}
return 0;
}