• bzoj 2555: SubString


    显然,在后缀自动机的后缀树上插入一个后缀后,此时表示整串的节点(np)到根的所有节点,其表示的串作为子串的出现次数都要+1;发现需要链修改,动态连边/删边,因此用LCT维护

    注意:虽然没明确写,但根据讨论区以及做题情况,此题字符集只有AB两个字母

    错误记录:没有msk^=res

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 using namespace std;
      5 int Add(int a,int b)    {return a+b;}
      6 int Add(int a,int b,int c)    {return a+b+c;}
      7 int Mul(int a,int b)    {return a*b;}
      8 namespace LCT
      9 {
     10 const int N=1200000;
     11 struct Node
     12 {
     13     Node *ch[2],*fa;
     14     bool rev;
     15     int addv;
     16     int dat,sz;
     17     void upd()    {sz=(ch[0]?ch[0]->sz:0)+1+(ch[1]?ch[1]->sz:0);}
     18     void padd(int x)    {addv=Add(addv,x);dat=Add(dat,x);}
     19     void pd()
     20     {
     21         if(rev)
     22         {
     23             swap(ch[0],ch[1]);
     24             if(ch[0])    ch[0]->rev^=1;
     25             if(ch[1])    ch[1]->rev^=1;
     26             rev=0;
     27         }
     28         if(addv)
     29         {
     30             if(ch[0])    ch[0]->padd(addv);
     31             if(ch[1])    ch[1]->padd(addv);
     32             addv=0;
     33         }
     34     }
     35     bool isroot()    {return (!fa)||(this!=fa->ch[0]&&this!=fa->ch[1]);}
     36     bool gson()    {return this==fa->ch[1];}
     37     void rot()//将自身向上旋,要求已经完成下传标记
     38     {
     39         bool d=gson();Node *f=fa;
     40         fa=f->fa;if(!f->isroot())    f->fa->ch[f->gson()]=this;
     41         f->ch[d]=ch[!d];if(ch[!d])    ch[!d]->fa=f;
     42         f->fa=this;ch[!d]=f;
     43         f->upd();upd();
     44     }
     45 }nodes[N+100];
     46 Node *st[N+100];int top;
     47 int mem;
     48 Node *getnode()
     49 {
     50     Node *t=nodes+mem++;t->sz=1;//t->ch[0]=t->ch[1]=t->fa=0;t->rev=t->addv=t->dat=0;
     51     return t;
     52 }
     53 void solvetag(Node *o)
     54 {
     55     while(!o->isroot())    st[++top]=o,o=o->fa;
     56     st[++top]=o;
     57     while(top)    st[top--]->pd();
     58 }
     59 void splay(Node *o)
     60 {
     61     solvetag(o);
     62     for(;!o->isroot();o->rot())
     63         if(!o->fa->isroot())
     64             o->gson()==o->fa->gson()?o->fa->rot():o->rot();
     65 }
     66 void acc(Node *o)
     67 {
     68     for(Node *lst=0;o;lst=o,o=o->fa)
     69         splay(o),o->ch[1]=lst,o->upd();
     70 }
     71 void mtop(Node *o)    {acc(o);splay(o);o->rev^=1;}
     72 void link(Node *x,Node *y)    {acc(x);splay(x);x->fa=y;}//保证x是根,使x成为y子节点
     73 void cut(Node *x)    {acc(x);splay(x);x->ch[0]->fa=0;x->ch[0]=0;}//断开x与父亲
     74 void add(Node *y,int t)    {acc(y);splay(y);y->padd(t);}//y到根路径+t
     75 int query(Node *y)    {splay(y);return y->dat;}//查询y单点的权值
     76 }
     77 using LCT::Node;using LCT::link;using LCT::getnode;using LCT::cut;using LCT::query;
     78 namespace SAM
     79 {
     80 int mem,np,root;
     81 int len[1200100],fa[1200100],trans[1200100][3];
     82 Node *nd[1200100];
     83 void append(int c)
     84 {
     85     int p=np;np=++mem;len[np]=len[p]+1;nd[np]=getnode();
     86     for(;p&&trans[p][c]==0;p=fa[p])    trans[p][c]=np;
     87     if(!p)    link(nd[np],nd[root]),fa[np]=root;
     88     else
     89     {
     90         int q=trans[p][c];
     91         if(len[q]==len[p]+1)    link(nd[np],nd[q]),fa[np]=q;
     92         else
     93         {
     94             int nq=++mem;nd[nq]=getnode();nd[nq]->dat=query(nd[q]);
     95             cut(nd[q]);link(nd[nq],nd[fa[q]]);link(nd[q],nd[nq]);link(nd[np],nd[nq]);
     96             fa[nq]=fa[q];fa[q]=fa[np]=nq;
     97             memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1;
     98             for(;p&&trans[p][c]==q;p=fa[p])    trans[p][c]=nq;
     99         }
    100     }
    101     LCT::add(nd[np],1);
    102 }
    103 int query(const char *ss,int len)
    104 {
    105     int now=root,i;
    106     for(i=0;i<len;i++)
    107     {
    108         now=trans[now][ss[i]-'A'];
    109         if(!now)    return 0;
    110     }
    111     return query(nd[now]);
    112 }
    113 }
    114 char tmp[3000100],ttt[10];int len,q;
    115 void decode(int msk)
    116 {
    117     for(int j=0;j<len;j++)
    118     {
    119         msk=(msk*131+j)%len;
    120         swap(tmp[j],tmp[msk]);
    121     }
    122 }
    123 int main()
    124 {
    125     int msk=0,res,i;SAM::np=SAM::root=++SAM::mem;SAM::nd[SAM::root]=getnode();
    126     scanf("%d",&q);
    127     scanf("%s",tmp);len=strlen(tmp);
    128     for(i=0;i<len;i++)    SAM::append(tmp[i]-'A');
    129     while(q--)
    130     {
    131         scanf("%s",ttt);
    132         if(ttt[0]=='A')
    133         {
    134             scanf("%s",tmp);len=strlen(tmp);decode(msk);
    135             for(i=0;i<len;i++)    SAM::append(tmp[i]-'A');
    136         }
    137         else if(ttt[0]=='Q')
    138         {
    139             scanf("%s",tmp);len=strlen(tmp);decode(msk);
    140             res=SAM::query(tmp,len);msk^=res;printf("%d
    ",res);
    141         }
    142     }
    143     return 0;
    144 }
  • 相关阅读:
    Oracle查询错误分析:ORA-01791:不是SELECTed表达式
    Java中DESKeySpec类
    linux发布项目
    mac下搭建cocos2d-x2.2.1版本android编译环境教程
    使用Eigen求解线性方程组
    视觉SLAM十四讲课后答案-ch1
    costmap_2d: obstacle_layer中关于激光雷达障碍物清除不干净的解决
    ch4 激光的前端配准算法一 —— ICP方法
    Project 'cv_bridge' specifies '/usr/include/opencv' as an include dir, which is not found.
    ch3 传感器数据处理II: 激光雷达运动畸变去除
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9021577.html
Copyright © 2020-2023  润新知