• 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 }
  • 相关阅读:
    URAL——DFS找规律——Nudnik Photographer
    URAL1353——DP——Milliard Vasya's Function
    URAL1203——DPor贪心——Scientific Conference
    递推DP HDOJ 5389 Zero Escape
    区间DP UVA 1351 String Compression
    树形DP UVA 1292 Strategic game
    Manacher HDOJ 5371 Hotaru's problem
    同余模定理 HDOJ 5373 The shortest problem
    递推DP HDOJ 5375 Gray code
    最大子序列和 HDOJ 1003 Max Sum
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10046348.html
Copyright © 2020-2023  润新知