zoukankan      html  css  js  c++  java
  • BZOJ 2555 SubString (后缀自动机+LCT)

    题目大意:

    让你维护一个文本串,支持在末尾插入字符,以及查询某个模式串在其中出现了多少次

    什么sd题

    $LCT$动态维护$parent$树,再用[BJOI2014]大融合的方法维护子树大小就行了

    不要像我一样把LCT打错了

    另外猫琨说这道题字符集开到2就行了,数据里只有A和B

      1 #include <cmath>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 605000
      7 #define S1 (N1<<1)
      8 #define L1 3000100
      9 #define ll long long
     10 #define uint unsigned int
     11 #define rint register int 
     12 #define dd double
     13 #define il inline 
     14 #define inf 0x3f3f3f3f
     15 #define idx(X) (X-'A')
     16 using namespace std;
     17 
     18 int gint()
     19 {
     20     int ret=0,fh=1;char c=getchar();
     21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     23     return ret*fh;
     24 }
     25 const int seed=131;
     26 int Q,len;
     27 char str[L1];
     28 namespace LCT{
     29 int ch[S1][2],fa[S1],stk[S1],sz[S1],sum[S1],sta[S1],rev[S1],tp;
     30 int idf(int x){return ch[fa[x]][0]==x?0:1;}
     31 int isroot(int x){return (ch[fa[x]][0]==x||ch[fa[x]][1]==x)?0:1;}
     32 void revers(int x){swap(ch[x][0],ch[x][1]);rev[x]^=1;}
     33 void pushup(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+sz[x]+sta[x];}
     34 void pushdown(int x){if(rev[x]){revers(ch[x][0]),revers(ch[x][1]),rev[x]^=1;}}
     35 void rot(int x)
     36 {
     37     int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     38     if(!isroot(y)) ch[ff][py]=x;fa[x]=ff;
     39     ch[y][px]=ch[x][px^1],fa[ch[x][px^1]]=y;
     40     ch[x][px^1]=y,fa[y]=x;
     41     pushup(y),pushup(x);
     42 }
     43 void splay(int x)
     44 {
     45     int y=x;stk[++tp]=x;
     46     while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
     47     while(tp){pushdown(stk[tp--]);}
     48     while(!isroot(x))
     49     {
     50         y=fa[x];
     51         if(isroot(y)) rot(x);
     52         else if(idf(x)==idf(y)) rot(y),rot(x);
     53         else rot(x),rot(x);
     54     }
     55     pushup(x);
     56 }
     57 void access(int x)
     58 {
     59     for(int y=0;x;y=x,x=fa[x]){
     60         splay(x);
     61         sz[x]-=sum[y];
     62         sz[x]+=sum[ch[x][1]];
     63         ch[x][1]=y,pushup(x);
     64     }
     65 }
     66 void mkroot(int x){access(x),splay(x),revers(x);}
     67 int findroot(int x)
     68 {
     69     access(x);
     70     splay(x);
     71     while(1){
     72         pushdown(x);
     73         if(ch[x][0]) x=ch[x][0];
     74         else break;}
     75     return x;
     76 }
     77 void link(int x,int y){
     78     mkroot(y);
     79         if(findroot(x)!=y) fa[x]=y,sz[y]+=sum[x];}
     80 void cut(int x,int y)
     81 {
     82     mkroot(y);
     83     if(findroot(x)==y && !ch[y][1] && ch[x][0]==y && fa[y]==x)
     84         ch[x][0]=fa[y]=0,pushup(x);
     85 }
     86 int query(int x,int rt)
     87 {
     88     mkroot(rt),access(x),splay(x);
     89     return sum[x]-sum[ch[x][0]];
     90 }
     91 };
     92 namespace SAM{
     93 int trs[S1][2],pre[S1],dep[S1],la,tot;
     94 void init(){la=tot=1;}
     95 void insert(int c)
     96 {
     97     int p=la,np=++tot,q,nq;la=np;
     98     dep[np]=dep[p]+1;
     99     LCT::sta[np]=1;
    100     for(;p&&!trs[p][c];p=pre[p]) trs[p][c]=np;
    101     if(!p){LCT::link(np,1);pre[np]=1;return;}
    102     q=trs[p][c];
    103     if(dep[q]==dep[p]+1){
    104         LCT::link(np,q);
    105         pre[np]=q;
    106     }else{
    107         pre[nq=++tot]=pre[q];
    108         LCT::cut(q,pre[q]);
    109         LCT::link(nq,pre[q]);
    110         pre[q]=pre[np]=nq;
    111         LCT::link(q,nq);
    112         LCT::link(np,nq);
    113         dep[nq]=dep[p]+1;
    114         memcpy(trs[nq],trs[q],sizeof(trs[q]));
    115         for(;p&&trs[p][c]==q;p=pre[p]) trs[p][c]=nq;
    116     }
    117 }
    118 int find(int L)
    119 {
    120     int x=1;
    121     for(int i=0;i<L;i++)
    122     {
    123         x=trs[x][idx(str[i])];
    124         if(!x) return 0;
    125     }
    126     return LCT::query(x,1);
    127 }
    128 };
    129 char op[10];
    130 int mask,tmp;
    131 
    132 int main()
    133 {
    134     //freopen("t4.in","r",stdin);
    135     scanf("%d",&Q);
    136     scanf("%s",str+1);
    137     len=strlen(str+1);
    138     SAM::init();
    139     for(int i=1;i<=len;i++) SAM::insert(idx(str[i]));
    140     for(int i=1;i<=Q;i++)
    141     {
    142         scanf("%s",op);scanf("%s",str);
    143         len=strlen(str);
    144         tmp=mask;
    145         for(int j=0;j<len;j++){
    146             tmp=(tmp*seed+j)%len;
    147             swap(str[j],str[tmp]);}
    148         if(op[0]=='A'){
    149             //for(int j=0;j<3;j++) printf("%c",op[j]);printf(" ");
    150             for(int j=0;j<len;j++)
    151                 SAM::insert(idx(str[j]));
    152         }else{
    153             int ans=SAM::find(len);
    154             printf("%d
    ",ans);
    155             mask^=ans;
    156             //for(int j=0;j<5;j++) printf("%c",op[j]);printf(" ");
    157         }
    158         /*for(int j=0;j<len;j++) printf("%c",str[j]);
    159         puts("");*/
    160     }
    161     return 0;
    162 }
  • 相关阅读:
    httpclient妙用一 httpclient作为客户端调用soap webservice(转)
    WebService学习总结(转)
    C++的override和final
    C++类const和static成员初始化
    C++数据存储方式
    C++类成员存储大小
    内联函数
    C++接口的概念
    C++深拷贝和浅拷贝
    C++构造函数以及何时被调用
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10104022.html
Copyright © 2011-2022 走看看