zoukankan      html  css  js  c++  java
  • BZOJ2555 SubString【后缀自动机+LCT】

    Description

    懒得写背景了,给你一个字符串init,要求你支持两个操作
    (1):在当前字符串的后面插入一个字符串
    (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
    你必须在线支持这些操作。

    Input

    第一行一个数Q表示操作个数
    第二行一个字符串表示初始字符串init
    接下来Q行,每行2个字符串Type,Str
    Type是ADD的话表示在后面插入字符串。
    Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
    为了体现在线操作,你需要维护一个变量mask,初始值为0

    读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
    询问的时候,对TrueStr询问后输出一行答案Result
    然后mask=maskxorResult
    插入的时候,将TrueStr插到当前字符串后面即可。

    HINT:ADD和QUERY操作的字符串都需要解压

    长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
    新加数据一组--2015.05.20

    Output

    Sample Input

    2
    A
    QUERY B
    ADD BBABBBBAAB

    Sample Output

    0


    思路

    用LCT来维护prt树的链接关系
    直接在extend的时候维护关系就可以了
    注意o节点要和先前的节点断开关系
    然后顺便维护siz集合的大小就可以了


    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define fu(a,b,c) for(int a=b;a<=c;++a)
    #define fd(a,b,c) for(int a=b;a>=c;--a)
    #define N 6000010
    //Link_Cut_Tree
    struct Splay{
      Splay *fa,*ch[2];
      int siz,add;
    }_null,*null=&_null;
    Splay *newnode(int vl=0){
      Splay *t=new Splay;
      t->siz=vl;
      t->fa=t->ch[1]=t->ch[0]=null;
      return t;
    }
    bool son(Splay *t){return t->fa->ch[1]==t;}
    bool isroot(Splay *t){return t->fa->ch[0]!=t&&t->fa->ch[1]!=t;}
    void pushnow(Splay *x,int vl){x->add+=vl;x->siz+=vl;}
    void pushdown(Splay *t){
      if(!isroot(t))pushdown(t->fa);
      if(t->add){
        if(t->ch[0]!=null)pushnow(t->ch[0],t->add);
        if(t->ch[1]!=null)pushnow(t->ch[1],t->add);
        t->add=0;
      }
    }
    void rotate(Splay *t){
      Splay *f=t->fa,*g=f->fa;
      bool a=son(t),b=a^1;
      if(!isroot(f))g->ch[son(f)]=t;
      t->fa=g;
      f->ch[a]=t->ch[b];t->ch[b]->fa=f;
      t->ch[b]=f;f->fa=t;
    }
    void splay(Splay *t){
      pushdown(t);
      while(!isroot(t)){
        Splay *f=t->fa;
        if(!isroot(f)){
          if(son(t)^son(f))rotate(t);
          else rotate(f);
        }
        rotate(t);
      }
    }
    void access(Splay *t){
      Splay *tmp=null;
      while(t!=null){
        splay(t);
        t->ch[1]=tmp;
        tmp=t;t=t->fa;
      }
    }
    void link(Splay *x,Splay *y){
      access(y);
      splay(y);
      x->fa=y;
      pushnow(y,x->siz);
    }
    void cut(Splay *x){
      access(x);
      splay(x);
      pushnow(x->ch[0],-x->siz);
      x->ch[0]->fa=null;
      x->ch[0]=null;
    }
    //Suffix_Automaton
    const int CHARSET_SIZE=26;
    struct Sam{
      Sam *ch[CHARSET_SIZE],*prt;
      Splay *right;
      int maxl;
      Sam(int vl=0,int siz=0){
        prt=NULL;
        memset(ch,0,sizeof(ch));
        maxl=vl;
        right=newnode(siz);
      }
    }*root=new Sam,*last=root;
    void extend(int c){
      Sam *u=new Sam(last->maxl+1,1),*v=last;
      for(;v&&!v->ch[c];v=v->prt)v->ch[c]=u;
      if(!v){
        u->prt=root;
        link(u->right,root->right);
      }else if(v->maxl+1==v->ch[c]->maxl){
        u->prt=v->ch[c];
        link(u->right,v->ch[c]->right);
      }else{
        Sam *n=new Sam(v->maxl+1,0),*o=v->ch[c];
        copy(o->ch,o->ch+CHARSET_SIZE,n->ch);
        n->prt=o->prt;
        link(n->right,o->prt->right);
        o->prt=u->prt=n;
        cut(o->right);
        link(o->right,n->right);
        link(u->right,n->right);
        for(;v&&v->ch[c]==o;v=v->prt)v->ch[c]=n;
      }
      last=u;
    }
    //solve and main
    char s[N],op[10];
    int len,mask=0;
    void decode(int m){
      fu(i,0,len-1){
        m=(m*131+i)%len;
        swap(s[i],s[m]);
      }
    }
    int main(){
      //freopen("input.txt","r",stdin);
      int q;scanf("%d",&q);
      scanf("%s",s);
      len=strlen(s);
      fu(i,0,len-1)extend(s[i]-'A');
      while(q--){
        scanf("%s %s",op,s);
        len=strlen(s);
        decode(mask);
        if(op[0]=='Q'){
          Sam *now=root;
          int can=1;
          fu(i,0,len-1){
            int c=s[i]-'A';
            if(!now->ch[c]){can=0;break;}
            now=now->ch[c];
          }
          if(!can){printf("0
    ");continue;}
          splay(now->right);
          mask^=now->right->siz;
          printf("%d
    ",now->right->siz);
        }else fu(i,0,len-1)extend(s[i]-'A');
      }
      return 0;
    }
    
  • 相关阅读:
    Java反射
    安装python
    查看网页加载速度,并优化
    模型按一个圈摆放(10等分)
    y = n*x 匀速,变速运动
    物体绕圆形做圆周运动
    three.js 相机跟随鼠标移动
    three.js 物体随鼠标移动
    three.js 画正多边形-线性
    ES6的JavaScript数据结构实现之队列
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9709179.html
Copyright © 2011-2022 走看看