• 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
    ",query());
        }
        return 0;   
    }
  • 相关阅读:
    7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)
    6、JPA_映射单向多对一的关联关系(n的一方有1的引用,1的一方没有n的集合属性)
    解决ubuntu的screen已经处于Attached状态,无法再打开窗口
    关于.ssh出错,无法从远程git仓库拉代码
    给程序添加git commit信息
    ubuntu服务器常用命令
    uint128_t 添加 c++ 重载类型强制转换
    Visual Studio 查看宏展开
    EOS dice移到1.8版本的修改汇总
    ubuntu 添加字体
  • 原文地址:https://www.cnblogs.com/shenben/p/6848469.html
Copyright © 2020-2023  润新知