zoukankan      html  css  js  c++  java
  • 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
    ",ans);
                mask^=ans;
            }
            else sol.add();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    题解-CF1097F Alex and a TV Show
    题解-UVA757 Gone Fishing
    题解-UVA1401 Remember the Word
    题解-UVA11732 "strcmp()" Anyone?
    【数学】[AH2017/HNOI2017]礼物
    Educational Codeforces Round 109
    KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)
    Codeforces Global Round 14
    CF906E Reverses(H)
    【LuoguP4464】 [国家集训队] JZPKIL(M)
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4623605.html
Copyright © 2011-2022 走看看