1. 程式人生 > >2555: SubString[LCT+SAM]

2555: SubString[LCT+SAM]

stat %20 scu ear led names mono desc 一行

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

Ctsc模擬賽By 潔妹

 

  • 答案顯然是目標串狀態的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]