zoukankan      html  css  js  c++  java
  • bzoj2555(lct维护sam)

    题意:
      (1):在当前字符串的后面插入一个字符串
      (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
      字符串长度<=6e5,询问总长度<=3e6
    分析:
      考虑建个sam,然后把slink连起来就形成了一个前缀树
      对于每个询问的串,就是求出它在sam里对应的点,然后在slink树种该点子树的size就是答案
      用lct维护slink树即可
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1200000;
      4 const int maxs=3e6;
      5 
      6 struct LCT
      7 {
      8     int ch[maxn+5][2],fa[maxn+5],flip[maxn+5];
      9     int top;
     10     int q[maxn+5];
     11     int sz[maxn+5];
     12     int tag[maxn+5];
     13     void init()
     14     {
     15 
     16     }
     17     bool isroot(int x)
     18     {
     19         return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
     20     }
     21     void add(int x,int data)
     22     {
     23         if(x)
     24         {
     25             tag[x]+=data;
     26             sz[x]+=data;
     27         }
     28     }
     29     void pushdown(int x)
     30     {
     31         int l=ch[x][0],r=ch[x][1];
     32         if(flip[x])
     33         {
     34             flip[x]^=1;flip[l]^=1;flip[r]^=1;
     35             swap(ch[x][0],ch[x][1]);
     36         }
     37         if(tag[x])
     38         {
     39             add(l,tag[x]),add(r,tag[x]);
     40             tag[x]=0;
     41         }
     42     }
     43     void rotate(int &x)
     44     {
     45         int y=fa[x],z=fa[y],l,r;
     46         if(ch[y][0]==x) l=0;
     47         else l=1;
     48         r=l^1;
     49         if(!isroot(y))
     50         {
     51             if(ch[z][0]==y) ch[z][0]=x;
     52             else ch[z][1]=x;
     53         }
     54         fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
     55         ch[y][l]=ch[x][r];ch[x][r]=y;
     56     }
     57     void splay(int &x)
     58     {
     59         top=0;
     60         q[++top]=x;
     61         for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
     62         while(top) pushdown(q[top--]);
     63         while(!isroot(x))
     64         {
     65             int y=fa[x],z=fa[y];
     66             if(!isroot(y))
     67             {
     68                 if(ch[y][0]==x^ch[z][0]==y) rotate(x);
     69                 else rotate(y);
     70             }
     71             rotate(x);
     72         }
     73     }
     74     void access(int x)
     75     {
     76         for(int t=0;x;t=x,x=fa[x])
     77             splay(x),ch[x][1]=t;
     78     }
     79     void link(int x,int f)
     80     {
     81         fa[x]=f;
     82         access(f);
     83         splay(f);
     84         add(f,sz[x]);
     85     }
     86     void cut(int x)
     87     {
     88         access(x);
     89         splay(x);
     90         add(ch[x][0],-sz[x]);
     91         fa[ch[x][0]]=0,ch[x][0]=0;
     92     }
     93     int query(int x)
     94     {
     95         access(x);
     96         splay(x);
     97         return sz[x];
     98     }
     99 }lct;
    100 
    101 struct SAM
    102 {
    103     int maxlen[maxn+50],minlen[maxn+50],trans[maxn+50][26],slink[maxn+50];
    104     int sz,last;
    105     void init()
    106     {
    107         for(int i=0;i<26;++i) trans[1][i]=slink[1]=-1;
    108         maxlen[1]=minlen[1]=0;
    109         sz=1;
    110         last=1;
    111     }
    112     int build(int _maxlen,int _minlen,int* _trans,int _slink)
    113     {
    114         maxlen[++sz]=_maxlen;
    115         minlen[sz]=_minlen;
    116         for(int i=0;i<26;++i)
    117             if(_trans==NULL) trans[sz][i]=-1;else trans[sz][i]=_trans[i];
    118         slink[sz]=_slink;
    119         return sz;
    120     }
    121     int add(char ch,int u)
    122     {
    123         int c=ch-'A';
    124         int z=build(maxlen[u]+1,-1,NULL,-1);
    125         lct.sz[z]=1;
    126         int v=u;
    127         while(v!=-1&&trans[v][c]==-1)
    128         {
    129             trans[v][c]=z,v=slink[v];
    130         }
    131         if(v==-1)//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
    132         {
    133             minlen[z]=1;
    134             slink[z]=1;
    135             lct.link(z,1);
    136             return z;
    137         }
    138         int x=trans[v][c];
    139         if(maxlen[v]+1==maxlen[x])//较简单的情况,不用拆分x
    140         {
    141             minlen[z]=maxlen[x]+1;
    142             slink[z]=x;
    143             lct.link(z,x);
    144             return z;
    145         }
    146         int y=build(maxlen[v]+1,-1,trans[x],slink[x]); //最复杂的情况,拆分x,y表示<=maxlen[v]+1的那段
    147         slink[y]=slink[x];
    148         lct.link(y,slink[y]);
    149         minlen[x]=maxlen[y]+1;
    150         lct.cut(x);
    151         slink[x]=y;
    152         lct.link(x,y);
    153         minlen[z]=maxlen[y]+1;
    154         slink[z]=y;
    155         lct.link(z,y);
    156         int w=v;
    157         while(w!=-1&&trans[w][c]==x) trans[w][c]=y,w=slink[w];
    158         minlen[y]=maxlen[slink[y]]+1;
    159         return z;
    160     }
    161     void append(char *s)
    162     {
    163         int len=strlen(s);
    164         for(int i=0;i<len;++i) last=add(s[i],last);
    165     }
    166     int query(char *s)
    167     {
    168         int len=strlen(s);
    169         int now=1;
    170         for(int i=0;i<len;++i)
    171         {
    172             now=trans[now][s[i]-'A'];
    173             if(now==-1) return 0;
    174         }
    175         return lct.query(now);
    176     }
    177 }sam;
    178 char s[maxs+5];
    179 int mask=0;
    180 void gets(int mask)
    181 {
    182     scanf("%s",s);
    183     int len=strlen(s);
    184     for (int j=0;j<len;j++)
    185     {
    186         mask=(mask*131+j)%len;
    187         char t=s[j];
    188         s[j]=s[mask];
    189         s[mask]=t;
    190     }
    191 }
    192 int main()
    193 {
    194     int q;
    195     scanf("%d",&q);
    196     sam.init();
    197     scanf("%s",s);
    198     sam.append(s);
    199     while(q--)
    200     {
    201         scanf("%s",s);
    202         if(s[0]=='A')
    203         {
    204             gets(mask);
    205             sam.append(s);
    206         }
    207         else
    208         {
    209             gets(mask);
    210             int ans=sam.query(s);
    211             mask^=ans;
    212             printf("%d
    ",ans);
    213         }
    214     }
    215     return 0;
    216 }
    View Code
  • 相关阅读:
    angularjs制作的iframe后台管理页切换页面
    javascript读取本地文件
    nginx Engine X静态网页服务器介绍
    关于 bounds 和 frame
    iOS 开发常见函数
    HTTP POST GET 本质区别详解(转)
    从 UIAlertView 到 UIAlertController
    学习 AFNetworking 3.0
    UICollectionView详解
    UITableView整理
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8859403.html
Copyright © 2011-2022 走看看