• BZOJ2555: SubString(后缀自动机,LCT维护Parent树)


    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

    解题思路:

    从后缀自动机构造的时候入手,因为Parent树是与pre指针直接相关,就在pre指针构造的时候快速维护Parent(LCT)。
    剩下的就是两个模板堆叠,没什么思维含量。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll tr[spc].ch[0]
      5 #define rrr tr[spc].ch[1]
      6 #define ls ch[0]
      7 #define rs ch[1]
      8 class Unzip{
      9     public:
     10         void update(int lastans)
     11         {
     12             mask^=lastans;
     13             return ;
     14         }
     15         void decode(int *a,int len)
     16         {
     17             int upg=mask;
     18             for(int i=1;i<=len;i++)
     19                 tmp[i-1]=a[i];
     20             for(int i=0;i<len;i++)
     21             {
     22                 upg=(upg*131+i)%len;
     23                 std::swap(tmp[i],tmp[upg]);
     24             }
     25             for(int i=1;i<=len;i++)
     26                 a[i]=tmp[i-1];
     27             return ;
     28         }
     29     private:
     30         int tmp[1000000];
     31         int mask;
     32 }U;
     33 struct trnt{
     34     int ch[2];
     35     int fa;
     36     int is;
     37     int lzt;
     38     int wgt;
     39     int wgti;
     40     bool anc;
     41 }tr[3000000];
     42 struct sant{
     43     int tranc[26];
     44     int len;
     45     int pre;
     46 }s[3000000];
     47 int Q;
     48 int siz;
     49 int fin;
     50 int lasans;
     51 char tmp[1000000];
     52 int atp[1000000];
     53 bool whc(int spc)
     54 {
     55     return tr[tr[spc].fa].rs==spc;
     56 }
     57 void pushup(int spc)
     58 {
     59     tr[spc].wgt=tr[spc].wgti+tr[spc].is+tr[lll].wgt+tr[rrr].wgt;
     60     return ;
     61 }
     62 void trr(int spc)
     63 {
     64     if(!spc)
     65         return ;
     66     std::swap(lll,rrr);
     67     tr[spc].lzt^=1;
     68     return ;
     69 }
     70 void pushdown(int spc)
     71 {
     72     if(tr[spc].lzt)
     73     {
     74         trr(lll);
     75         trr(rrr);
     76         tr[spc].lzt=0;
     77     }
     78     return ;
     79 }
     80 void recal(int spc)
     81 {
     82     if(!tr[spc].anc)
     83         recal(tr[spc].fa);
     84     pushdown(spc);
     85     return ;
     86 }
     87 void rotate(int spc)
     88 {
     89     int f=tr[spc].fa;
     90     bool k=whc(spc);
     91     tr[f].ch[k]=tr[spc].ch[!k];
     92     tr[spc].ch[!k]=f;
     93     if(tr[f].anc)
     94     {
     95         tr[f].anc=0;
     96         tr[spc].anc=1;
     97     }else
     98         tr[tr[f].fa].ch[whc(f)]=spc;
     99     tr[spc].fa=tr[f].fa;
    100     tr[f].fa=spc;
    101     tr[tr[f].ch[k]].fa=f;
    102     pushup(f);
    103     pushup(spc);
    104     return ;
    105 }
    106 void splay(int spc)
    107 {
    108     recal(spc);
    109     while(!tr[spc].anc)
    110     {
    111         int f=tr[spc].fa;
    112         if(tr[f].anc)
    113         {
    114             rotate(spc);
    115             return ;
    116         }
    117         if(whc(spc)^whc(f))
    118             rotate(spc);
    119         else
    120             rotate(f);
    121         rotate(spc);
    122     }
    123     return ;
    124 }
    125 void access(int spc)
    126 {
    127     int lst=0;
    128     while(spc)
    129     {
    130         splay(spc);
    131         tr[spc].wgti-=tr[lst].wgt;
    132         tr[spc].wgti+=tr[rrr].wgt;
    133         tr[rrr].anc=1;
    134         tr[lst].anc=0;
    135         rrr=lst;
    136         pushup(spc);
    137         lst=spc;
    138         spc=tr[spc].fa;
    139     }
    140     return ;
    141 }
    142 void Mtr(int spc)
    143 {
    144     access(spc);
    145     splay(spc);
    146     trr(spc);
    147     return ;
    148 }
    149 void split(int x,int y)
    150 {
    151     Mtr(x);
    152     access(y);
    153     splay(y);
    154     return ;
    155 }
    156 void link(int x,int y)
    157 {
    158     split(x,y);
    159     tr[x].fa=y;
    160     tr[y].wgti+=tr[x].wgt;
    161     pushup(y);
    162     return ;
    163 }
    164 void cut(int x,int y)
    165 {
    166     split(x,y);
    167     tr[x].fa=0;
    168     tr[y].ls=0;
    169     tr[x].anc=1;
    170     pushup(y);
    171     return ;
    172 }
    173 void Insert(int c)
    174 {
    175     int nwp,nwq,lsp,lsq;
    176     nwp=++siz;
    177     tr[nwp].anc=1;
    178     tr[nwp].is=1;
    179     s[nwp].len=s[fin].len+1;
    180     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
    181         s[lsp].tranc[c]=nwp;
    182     if(!lsp)
    183     {
    184         s[nwp].pre=1;
    185         link(nwp,1);
    186     }else{
    187         lsq=s[lsp].tranc[c];
    188         if(s[lsq].len==s[lsp].len+1)
    189         {
    190             s[nwp].pre=lsq;
    191             link(nwp,lsq);
    192         }else{
    193             nwq=++siz;
    194             tr[nwq].anc=1;
    195             s[nwq]=s[lsq];
    196             cut(s[lsq].pre,lsq);
    197             link(s[nwq].pre,nwq);
    198             s[nwq].len=s[lsp].len+1;
    199             s[nwp].pre=s[lsq].pre=nwq;
    200             link(nwq,nwp);
    201             link(nwq,lsq);
    202             while(s[lsp].tranc[c]==lsq)
    203             {
    204                 s[lsp].tranc[c]=nwq;
    205                 lsp=s[lsp].pre;
    206             }
    207         }
    208     }
    209     fin=nwp;
    210     return ;
    211 }
    212 int Query(int root)
    213 {
    214     Mtr(1);
    215     access(root);
    216     return tr[root].wgti+tr[root].is;
    217 }
    218 int main()
    219 {
    220     fin=++siz;
    221     tr[fin].anc=1;
    222     scanf("%d",&Q);
    223     scanf("%s",tmp+1);
    224     int len=strlen(tmp+1);
    225     for(int i=1;i<=len;i++)
    226         Insert(tmp[i]-'A');
    227     while(Q--)
    228     {
    229         scanf("%s",tmp);
    230         if(tmp[0]=='A')
    231         {
    232             scanf("%s",tmp+1);
    233             len=strlen(tmp+1);
    234             for(int i=1;i<=len;i++)
    235                 atp[i]=tmp[i]-'A';
    236             U.decode(atp,len);
    237             for(int i=1;i<=len;i++)
    238                 Insert(atp[i]);
    239         }else{
    240             scanf("%s",tmp+1);
    241             len=strlen(tmp+1);
    242             for(int i=1;i<=len;i++)
    243                 atp[i]=tmp[i]-'A';
    244             U.decode(atp,len);
    245             int root=1;
    246             for(int i=1;i<=len;i++)
    247             {
    248                 root=s[root].tranc[atp[i]];
    249             
    250             }
    251             if(!root)
    252                 lasans=0;
    253             else
    254                 lasans=Query(root);
    255             printf("%d
    ",lasans);
    256             U.update(lasans);
    257         }
    258     }
    259     return 0;
    260 }
  • 相关阅读:
    c++语言 运算符重载 使用重载运算符实现类的加法运算
    c++语言 类模板的使用 类模板的实现
    C++语言 通过类模板实现加法计算器
    C++语言 对动物的行为实现多态
    c++语言 友元类和友元方法 将普通函数声明为友元函数
    C++语言 通过构造函数初始化学生信息
    c++语言 静态成员数据和静态方法
    欧拉回路心得
    POJ2965 The Pilots Brothers' refrigerator(枚举)
    HDU1269 迷宫城堡(有向图的强连通分量(scc))
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10046348.html
Copyright © 2020-2023  润新知