BZOJ2555: SubString

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

考虑修改的是模式串,可以用SAM,考虑动态修改,可以用LCT来维护fa指针与end-set集大小。
然后就是写代码的问题了。
get函数写错了调了半天233
注意:BZOJ不能写连等号(pre[ch[x][0]]=ch[x][0]=0;),否则会又R又T得飞起。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define lc ch[x][0]
#define rc ch[x][1]
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
const int maxn=1200010;
const int maxm=3000010;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
char s[maxm];
void get(int mask) {
    scanf("%s",s);int n=strlen(s);
    rep(0,n-1) {
        mask=(mask*131+i)%n;
        swap(s[i],s[mask]);
    }
}
int mask;
struct LCT {
    int fa[maxn],pre[maxn],ch[maxn][2],addv[maxn],w[maxn];
    void Add(int x,int y) {
        if(x) addv[x]+=y,w[x]+=y;
    }
    void pushdown(int x) {
        if(addv[x]) Add(lc,addv[x]),Add(rc,addv[x]);
        addv[x]=0;
    }
    void rotate(int x) {
        int y=pre[x],z=pre[y],d=ch[y][0]==x;
        ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
        ch[z][ch[z][1]==y]=x;pre[x]=z;
        ch[x][d]=y;pre[y]=x;
    }
    int top,S[maxn];
    void splay(int x) {
        for(int i=x;i;i=pre[i]) S[++top]=i;
        if(top!=1) fa[x]=fa[S[top]];
        while(top) pushdown(S[top--]);
        while(pre[x]) rotate(x);
    }
    void access(int x) {
        for(int y=0;x;x=fa[x]) {
            splay(x);fa[ch[x][1]]=x;pre[ch[x][1]]=0;
            ch[x][1]=y;pre[y]=x;y=x;
        }
    }
    void link(int x,int f) {fa[x]=f;access(f);splay(f);Add(f,w[x]);}
    void cut(int x) {access(x);splay(x);Add(ch[x][0],-w[x]);pre[ch[x][0]]=0;ch[x][0]=0;}
}lct;
struct SAM {
    int l[maxn],fa[maxn],to[maxn][26],cnt,last;
    SAM() {cnt=last=1;}
    void extend(int c) {
        int p,q,np,nq;
        p=last;last=++cnt;np=cnt;lct.w[np]=1;l[np]=l[p]+1;
        for(;!to[p][c];p=fa[p]) to[p][c]=np;
        if(!p) fa[np]=1,lct.link(np,1);
        else {
            q=to[p][c];
            if(l[p]+1==l[q]) fa[np]=q,lct.link(np,q);
            else {
                nq=++cnt;l[nq]=l[p]+1;
                memcpy(to[nq],to[q],sizeof(to[q]));
                fa[nq]=fa[q];lct.link(nq,fa[q]);
                fa[q]=nq;fa[np]=nq;lct.cut(q);lct.link(q,nq);lct.link(np,nq);
                for(;to[p][c]==q;p=fa[p]) to[p][c]=nq;
            }
        }
    }
    int query() {
        int p=1;
        for(int i=0;s[i];i++) if(!(p=to[p][s[i]-'A'])) return 0;
        lct.splay(p);return lct.w[p];
    }
    void add() {
        for(int i=0;s[i];i++) extend(s[i]-'A');
    }
}sol;
char cmd[12];
int main() {
    int n=read();scanf("%s",s);
    sol.add();
    while(n--) {
        scanf("%s",cmd);get(mask);
        if(cmd[0]=='Q') {
            int ans=sol.query();
            printf("%d\n",ans);
            mask^=ans;
        }
        else sol.add();
    }
    return 0;
}
View Code

 

posted @ 2015-07-06 10:09  wzj_is_a_juruo  阅读(274)  评论(0编辑  收藏  举报