bzoj千题计划285:bzoj2555: SubString

http://www.lydsy.com/JudgeOnline/problem.php?id=2555

 

后缀自动机,用LCT维护parent树

一个串的出现次数 = parent 树 上 其所在状态 的 子树 叶节点 | Right | 之和

若在parent中np的子节点中加一个节点p,设p的 | Right | = sum,那么 根节点到np 的整条链上的所有状态的 | Right | 都要 + sum

若更换掉q原来的父节点, 设q的 | Right | = sum,那么 根节点到q 的整条链上的所有状态的 | Right | 都要 -  sum

 

注意  decodeWithMask mask的修改 不影响全局的mask,全局的mask 只 会受 last_ans的影响  

 

三个 无脑shabi错误的血泪史:

 

 

#include<cstdio>
#include<cstring>
#include<iostream>
   
using namespace std;
   
#define N 600002
   
char s[3000001];
   
int tot=1,fa[N<<1],len[N<<1],ch[N<<1][26];
int p,q,np,nq,last=1;
   
int mask;
string chars;
   
int sum[N<<1],tag[N<<1];
int Sfa[N<<1],Sch[N<<1][2];
   
int st[N<<1],top;
   
void decodeWithMask(int mask)
{
    scanf("%s",s);
    chars=s;
    int n=chars.length();
    for (int j=0;j<n;j++) 
    {
        mask=(mask*131+j)%n;
        char t=chars[j];
        chars[j]=chars[mask];
        chars[mask]=t;
    }
}
   
bool isroot(int x)
{
    return Sch[Sfa[x]][0]!=x && Sch[Sfa[x]][1]!=x;
}
   
bool getson(int x)
{
    return Sch[Sfa[x]][1]==x;
}
   
void tagging(int x,int y)
{
    sum[x]+=y; tag[x]+=y;
}
   
void down(int x)
{
    if(!tag[x]) return;
    if(Sch[x][0]) tagging(Sch[x][0],tag[x]);
    if(Sch[x][1]) tagging(Sch[x][1],tag[x]);
    tag[x]=0;
}
   
void rotate(int x)
{
    int y=Sfa[x],z=Sfa[y]; int k=getson(x);
    if(!isroot(y)) Sch[z][Sch[z][1]==y]=x;
    Sch[y][k]=Sch[x][k^1]; Sch[x][k^1]=y;
    Sfa[x]=z; Sfa[y]=x; Sfa[Sch[y][k]]=y;
}
   
void splay(int x)
{
    st[top=1]=x;
    for(int i=x;!isroot(i);i=Sfa[i]) st[++top]=Sfa[i];
    for(int i=top;i;--i) down(st[i]);
    int y;
    while(!isroot(x))
    {
        y=Sfa[x];
        if(!isroot(y)) rotate(getson(y)==getson(x) ? y : x);
        rotate(x);
    }
}
   
void access(int x)
{
    int t=0;
    while(x)
    {
        splay(x);
        Sch[x][1]=t;
        t=x; x=Sfa[x];
    }
}
   
void link(int x,int f)
{
    Sfa[x]=f;
    access(f);
    splay(f);
    tagging(f,sum[x]);
}
   
void cut(int x)
{
    access(x);
    splay(x);
    tagging(Sch[x][0],-sum[x]);
    Sfa[Sch[x][0]]=0;
    Sch[x][0]=0;
}
   
void extend(int c)
{
    len[np=++tot]=len[last]+1;
    sum[np]++;
    for(p=last;p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
    if(!p) fa[np]=1,link(np,1);
    else
    {
        q=ch[p][c];
        if(len[q]==len[p]+1) fa[np]=q,link(np,q);
        else
        {
            len[nq=++tot]=len[p]+1;
            memcpy(ch[nq],ch[q],sizeof(ch[nq]));
            fa[nq]=fa[q]; link(nq,fa[q]);
            fa[q]=fa[np]=nq;
            cut(q); link(q,nq); link(np,nq);
            for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
        }
    }
    last=np;
}
   
void build()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int i=1;i<=n;++i) extend(s[i]-'A');
}
   
void add()
{
    decodeWithMask(mask);
    int n=chars.length();
    for(int i=0;i<n;++i) extend(chars[i]-'A');
}
   
int query()
{
    decodeWithMask(mask);
    int n=chars.length();
    int now=1;
    for(int i=0;i<n;++i)
        if(!(now=ch[now][chars[i]-'A'])) return 0;
    splay(now);
    return sum[now];
}
   
int main()
{
    int T,ans;
    scanf("%d",&T);
    build();
    while(T--)
    {
        scanf("%s",s);
        if(s[0]=='A') add();
        else
        {
            ans=query();
            printf("%d\n",ans);
            mask^=ans;
        }
    }
}

 

posted @ 2018-03-15 22:28  TRTTG  阅读(248)  评论(0编辑  收藏  举报