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\n",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 }

 

posted @ 2018-12-11 18:34  guapisolo  阅读(162)  评论(0编辑  收藏  举报