BZOJ 2555: SubString

BZOJ 2555: SubString

标签(空格分隔): OI-BZOJ OI-后缀自动机 OI-LCT


Time Limit: 30 Sec
Memory Limit: 512 MB


Description

懒得写背景了,给你一个字符串init,要求你支持两个操作

(1):在当前字符串的后面插入一个字符串

(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)

你必须在线支持这些操作。

Input

第一行一个数Q表示操作个数

第二行一个字符串表示初始字符串init

接下来Q行,每行2个字符串Type,Str 

Type是ADD的话表示在后面插入字符串。

Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。

为了体现在线操作,你需要维护一个变量mask,初始值为0

此处输入图片的描述

读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result  
插入的时候,将TrueStr插到当前字符串后面即可。

HINT:ADD和QUERY操作的字符串都需要解压

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

HINT

40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000

100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000

新加数据一组--2015.05.20


Solution

给一组自己玩的数据:
10
A
QUERY B
ADD BBABBBBAAB
QUERY AB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB

输出
0
3
4
3
6

构造后缀自动机,每个状态的right集合大小即为当前串的出现次数。
用LCT维护自动机的fail树在线得到每个点的right集合大小


Code

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
    return s*f;
}
//smile please
const int N=600005;
struct tree;
extern tree t[N*2];
struct tree
{
    int w[2],f,s,r,la;
    void down()
       {
        if(r)swap(w[0],w[1]);
        if(w[0])t[w[0]].r^=r;
        if(w[1])t[w[1]].r^=r;r=0;
        s+=la;
        if(w[0])t[w[0]].la+=la;
        if(w[1])t[w[1]].la+=la;
        la=0;
       }
    void updata()
       {
       }
}t[N*2];
bool notroot(int x)
{
    return t[t[x].f].w[0]==x||t[t[x].f].w[1]==x;
}
void rotate(int x)
{
    int f=t[x].f,r=(t[f].w[1]==x);
    t[x].f=t[f].f;
    if(notroot(f))
      t[t[f].f].w[t[t[f].f].w[1]==f]=x;
    t[f].w[r]=t[x].w[!r];
    if(t[x].w[!r])
      t[t[x].w[!r]].f=f;
    t[f].f=x;
    t[x].w[!r]=f;
    t[f].updata();
}
int sta[N*2];
void splay(int x)
{
    if(x==0)return;
    for(sta[++sta[0]]=x;notroot(sta[sta[0]]);)
        sta[++sta[0]]=t[sta[sta[0]-1]].f;
    while(sta[0])t[sta[sta[0]--]].down();
    for(int f;notroot(x);rotate(x))
        if(notroot(f=t[x].f))
          rotate(t[t[f].f].w[1]==f^t[f].w[1]==x?x:f);
    t[x].updata();
}
void access(int x){int xx=x;for(int las=0;x;splay(x),t[x].w[1]=las,las=x,x=t[x].f);splay(xx);}
struct samm
{
    int last,total;
    int L[N*2],ch[N*2][26],fa[N*2];//,val[N*2];
    samm(){total=1,last=1;}
    void plu(int x,int s)
       {//for(;x;x=fa[x])
        //    val[x]+=s;
        access(x);t[x].la+=s;
       }
    void fu(int x,int y)
       {
        splay(x),splay(y);
        if(fa[x])
           {if(t[x].s)plu(fa[x],-t[x].s);
            access(fa[x]);splay(x);t[x].f=0;
           }
        t[x].f=y;
        access(x);
        if(t[x].s)
          plu(y,t[x].s);
        fa[x]=y;
       }
    void insert(int C)
       {int p=last,now=last=++total;
        L[now]=L[p]+1;t[now].s=1;
        for(;p&&!ch[p][C];p=fa[p])
            ch[p][C]=now;
        if(!p){fu(now,1);return;}
        
        if(L[ch[p][C]]==L[p]+1){fu(now,ch[p][C]);return;}
        
        int ne=++total,Q=ch[p][C];
        memcpy(ch[ne],ch[Q],sizeof(ch[Q]));
        fu(ne,fa[Q]);
        fu(Q,ne);fu(now,ne);
        L[ne]=L[p]+1;
        for(;p&&ch[p][C]==Q;p=fa[p])
            ch[p][C]=ne;
       }
    int ST(char z[],int len)
       {int now=1;
        for(int i=0;i<len;i++)
            now=ch[now][z[i]-'A'];
        return now;
       }
    void print()
       {
        for(int i=1;i<=total;i++)
            printf("%d: f_%d l_%d a_%d b_%d c_%d\n",i,fa[i],L[i],ch[i][0],ch[i][1],ch[i][2]);
       }
}a;
int len;
char z[3000005];
int Q,mask;
void readstr()
{
    len=0;z[0]=getchar();
    while(z[0]<'A'||z[len]>'Z')z[0]=getchar();
    while(z[len]>='A'&&z[len]<='Z')z[++len]=getchar();
    z[len]=0;
}
void decode(int mask)
{
    for(int i=0;i<len;i++)
       {mask=(mask*131+i)%len;
        swap(z[i],z[mask]);
       }
}
int solve()
{
    int x=a.ST(z,len);
    splay(x);
    return t[x].s;
}
int main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    Q=read();
    readstr();
    for(int i=0;i<len;i++)
        a.insert(z[i]-'A');
    while(Q--)
       {readstr();
        if(z[0]=='A')
           {readstr();decode(mask);
            for(int i=0;i<len;i++)
                a.insert(z[i]-'A');
           }
        else
           {readstr();decode(mask);
            int ans=solve();
            mask^=ans;
            printf("%d\n",ans);
           }
       }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

posted on 2016-03-18 22:28  wuyuhan  阅读(...)  评论(...编辑  收藏

导航