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 }
人生如梦亦如幻 朝如晨露暮如霞。