2555: SubString[LCT+SAM]

Posted 神犇(shenben)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2555: SubString[LCT+SAM]相关的知识,希望对你有一定的参考价值。

2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 2601  Solved: 780
[Submit][Status][Discuss]

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

   

 

 

Source

 

 

  • 答案显然是目标串状态的right集合的大小,因为要在线我们可以用LCT来维护parent树。也就是说每次将当前点到根节点路径上right +1。 

 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
//---------------------LCT----------------------
const int M=3e6+10;
int n,m,fa[M],st[M],c[M][2];
bool rev[M];
int tag[M];
int val[M];
bool isroot(int x){
    return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
/*void update(int x){
    val[x]=val[c[x][0]]+val[c[x][1]]+1;
}*/
void opera(int x,int v){
    if(x) tag[x]+=v,val[x]+=v;
}
void rotate(int x){
    int y=fa[x],z=fa[y],l,r;
    l=(c[y][1]==x);r=l^1;
    if(!isroot(y)) c[z][c[z][1]==y]=x;
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    //update(y);update(x);
}
#define l c[x][0]
#define r c[x][1]
void pushdown(int x){
    /*if(rev[x]){
        rev[x]^=1;rev[l]^=1;rev[r]^=1;
        swap(l,r);
    }*/
    if(tag[x]){
        opera(l,tag[x]);
        opera(r,tag[x]);
        tag[x]=0;
    }
}
void splay(int x){
    int top=0;st[++top]=x;
    for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
    for(int i=top;i;i--) pushdown(st[i]);
    while(!isroot(x)){
        int y=fa[x],z=fa[y];
        if(!isroot(y)){
            if((c[y][0]==x)^(c[z][0]==y)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x){
    for(int t=0;x;x=fa[x]) splay(x),c[x][1]=t,t=x;
}
/*void evert(int x){
    access(x);splay(x);rev[x]^=1;
}*/
void link(int x,int y){
    fa[x]=y;access(y);splay(y);
    //evert(x);fa[x]=y;splay(x);
    opera(y,val[x]);
}
/*void cut(int x,int y){
    evert(x);
    access(y);splay(y);
    opera(y,-val[y]);
    c[y][0]=fa[c[y][0]]=0;//!!!
}*/
void cut(int x){
    access(x);splay(x);opera(l,-val[x]);
    c[x][0]=fa[c[x][0]]=0;
}
int find(int x){
    access(x);splay(x);
    for(;l;x=l);
    return x;
}
#undef l
#undef r
//---------------------SAM----------------------
const int N=1.2e6+5;
int p,q,np,nq;
int last,cnt,len,mask;
int l[N],par[N],tr[N][26];
int siz[N];char s[N];
inline void extend(int c){
    p=last;np=last=++cnt;val[np]=1;l[np]=l[p]+1;
    for(;p&&!tr[p][c];tr[p][c]=np,p=par[p]);
    if(!p) par[np]=1,link(np,1);
    else{
        q=tr[p][c];
        if(l[p]+1==l[q]) par[np]=q,link(np,q);
        else{
            nq=++cnt;l[nq]=l[p]+1;cut(q);
            memcpy(tr[nq],tr[q],sizeof tr[q]);
            par[nq]=par[q];
            link(nq,par[q]);
//            siz[nq]=siz[q];
            par[np]=par[q]=nq;
            link(np,nq);link(q,nq);
            for(;tr[p][c]==q;tr[p][c]=nq,p=par[p]);
        }
    }
//    for(;np;np=par[np]) siz[np]++;
}
inline void build(){
    for(int i=0;i<len;i++) extend(s[i]-A);
}
inline int query(){
    int p=1;
    for(int i=0,c;i<len;i++){
        c=s[i]-A;
        if(!tr[p][c]) return 0;
        p=tr[p][c];
    }
    splay(p);
    mask^=val[p];
    return val[p];
}
inline void decode(int mask){
    len=strlen(s);
    for(int i=0;i<len;i++){
        mask=(mask*131+i)%len;
        swap(s[mask],s[i]);
    }
}
int main(){
    last=++cnt;
    scanf("%d",&m);scanf("%s",s);len=strlen(s);
    build();
    for(char op[9];m--;){
        scanf("%s%s",op,s);decode(mask);
        if(op[0]==A) 
            build();
        else
            printf("%d\n",query());
    }
    return 0;   
}

 

以上是关于2555: SubString[LCT+SAM]的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2555 SubString(SAM+LCT)

[BZOJ2555]SubString(SAM+LCT)

bzoj2555: SubString sam+lct

BZOJ 2555 SubString 后缀自动机+LCT

bzoj2555: SubString

bzoj2555 SubString