bzoj2555 SubString

后缀自动机+LCT维护parent树

其实就是要求一个动态添加的right集合大小,每次添加改变的只有last以及他的parent链上的点,我们还要维护动态删边加边,于是LCT就是最好的选择。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define N 1205000
  7 using namespace std;
  8 char s[N<<3],opt[10];
  9 int n,m,mask;
 10 struct Node {
 11     Node *ch[2],*fa;
 12     int id,val,lazy;
 13     void update(int x){val+=x;lazy+=x;}
 14     void pushdown();
 15     Node(){};
 16 }*null=new Node(),tree[N];
 17 void Node :: pushdown(){
 18     if(lazy){
 19         if(ch[0]!=null)ch[0]->update(lazy);
 20         if(ch[1]!=null)ch[1]->update(lazy);
 21         lazy=0;
 22     }
 23 }
 24 void init(){
 25     null->ch[0]=null->ch[1]=null->fa=null;
 26     null->id=null->val=null->lazy=0;
 27     for(int i=1;i<N;i++){
 28         tree[i].ch[0]=tree[i].ch[1]=tree[i].fa=null;
 29         tree[i].lazy=tree[i].val=0;tree[i].id=i;
 30     }
 31 }
 32 void rotate(Node *x){
 33     Node *y=x->fa,*z=y->fa;
 34     int w=y->ch[1]==x;
 35     x->ch[w^1]->fa=y;y->ch[w]=x->ch[w^1];
 36     y->fa=x;x->ch[w^1]=y;
 37     if(z->ch[0]==y)z->ch[0]=x;
 38     if(z->ch[1]==y)z->ch[1]=x;
 39     x->fa=z;
 40 }
 41 bool isroot(Node *x){
 42     return x->fa->ch[0]!=x&&x->fa->ch[1]!=x;
 43 }
 44 int get(Node *x){
 45     if(x->fa->ch[0]==x)return 0;
 46     if(x->fa->ch[1]==x)return 1;
 47     return -1;
 48 }
 49 void pushdown(Node *x){
 50     if(!isroot(x))
 51         pushdown(x->fa);
 52     x->pushdown();
 53 }
 54 void splay(Node *x){
 55     Node *y;
 56     pushdown(x);
 57     while(!isroot(x)){
 58         y=x->fa;
 59         if(!isroot(y)){
 60             if(get(y)==get(x))rotate(y);
 61             else rotate(x);
 62         }rotate(x);
 63     }
 64 }
 65 void access(Node *x){
 66     Node *y=null;
 67     while(x!=null){
 68         splay(x);
 69         x->ch[1]=y;
 70         y=x;x=x->fa;
 71     }
 72 }
 73 void cut(Node *x,Node *y){
 74     access(y);splay(y);
 75     y->ch[0]=x->fa=null;
 76 }
 77 void link(Node *x,Node *y){
 78     access(y);splay(y);
 79     x->fa=y;
 80 }
 81 void update(Node *x){
 82     access(x);
 83     splay(x);
 84     x->update(1);
 85 }
 86 void query(Node *x){
 87     access(x);
 88     splay(x);
 89     printf("%d\n",x->val);
 90     mask^=x->val;
 91 }
 92 int last,tot,mx[N],par[N],ch[N][26];
 93 void add(int c){
 94     int p=last,np=++tot;mx[np]=mx[p]+1;
 95     for(;p&&!ch[p][c];p=par[p])ch[p][c]=np;
 96     if(!p)par[np]=1;
 97     else{
 98         int q=ch[p][c];
 99         if(mx[q]==mx[p]+1)par[np]=q;
100         else{
101             int nq=++tot;
102             access(&tree[q]);
103             splay(&tree[q]);
104             tree[nq].val=tree[q].val;
105             link(&tree[nq],&tree[par[q]]);
106             cut(&tree[par[q]],&tree[q]);
107             link(&tree[q],&tree[nq]);
108             mx[nq]=mx[p]+1;
109             par[nq]=par[q];
110             memcpy(ch[nq],ch[q],sizeof ch[nq]);
111             par[q]=par[np]=nq;
112             for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq;
113         }
114     }
115     link(&tree[np],&tree[par[np]]);
116     update(&tree[np]);
117     last=np;
118 }
119 void gets(int x){
120     scanf("%s",s);
121     n=strlen(s);
122     for(int j=0;j<n;j++){
123         x=(x*131+j)%n;
124         char t=s[j];s[j]=s[x];s[x]=t;
125     }
126 }
127 void dfs(int v,int x){
128     if(x==n){query(&tree[v]);return ;}
129     if(!ch[v][s[x]-'A']){puts("0");return ;}
130     else dfs(ch[v][s[x]-'A'],x+1);
131 }
132 int main(){
133     init();
134     last=++tot;
135     scanf("%d",&m);
136     scanf("%s",s);
137     n=strlen(s);
138     for(int i=0;i<n;i++)add(s[i]-'A');
139     while(m--){
140         scanf("%s",opt);
141         gets(mask);
142         if(opt[0]=='A')for(int i=0;i<n;i++)add(s[i]-'A');
143         else dfs(1,0);
144     }
145     return 0;
146 }
View Code

 

人生如梦亦如幻 朝如晨露暮如霞。
posted @ 2018-01-29 14:12  Ren_Ivan  阅读(145)  评论(0编辑  收藏  举报