BZOJ5408: string(广义后缀自动机,LCT)
解题思路:
首先在后缀树上,确定了一个节点就相当于确定了一个串,那么一个点对应的串在另外一个点对应的串产生贡献,当且仅当这个点在当前点子树内。
那么考虑一个新的点在串中对串答案的贡献在一条树链上或者反过来说,就是产生贡献的点在这个点子树内。
才知道自己写的广义后缀自动机板子是错的QAQ
考虑n非常小,贡献可以单独算,再配合BZOJ2555的启发,这道题就可以使用LCT轻松地解决了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lll tr[spc].ch[0] 5 #define rrr tr[spc].ch[1] 6 #define ls ch[0] 7 #define rs ch[1] 8 typedef long long lnt; 9 struct trnt{ 10 int ch[2]; 11 int fa; 12 int val[21]; 13 int lzt[21]; 14 bool anc; 15 }tr[1000000]; 16 struct sant{ 17 int tranc[26]; 18 int pre; 19 int len; 20 }s[1000000]; 21 int n,m; 22 lnt sum; 23 int siz; 24 int type; 25 int lastans; 26 int pos[21][200010]; 27 char str[400000]; 28 bool whc(int spc) 29 { 30 return tr[tr[spc].fa].rs==spc; 31 } 32 void add(int spc,int no,int v) 33 { 34 if(!spc)return ; 35 tr[spc].val[no]+=v; 36 tr[spc].lzt[no]+=v; 37 return ; 38 } 39 void pushdown(int spc) 40 { 41 for(int i=1;i<=n;i++) 42 { 43 if(tr[spc].lzt[i]) 44 { 45 add(lll,i,tr[spc].lzt[i]); 46 add(rrr,i,tr[spc].lzt[i]); 47 tr[spc].lzt[i]=0; 48 } 49 } 50 } 51 void recal(int spc) 52 { 53 if(!tr[spc].anc)recal(tr[spc].fa); 54 pushdown(spc); 55 return ; 56 } 57 void rotate(int spc) 58 { 59 int f=tr[spc].fa; 60 bool k=whc(spc); 61 tr[f].ch[k]=tr[spc].ch[!k]; 62 tr[spc].ch[!k]=f; 63 if(tr[f].anc) 64 { 65 tr[f].anc=false; 66 tr[spc].anc=true; 67 }else tr[tr[f].fa].ch[whc(f)]=spc; 68 tr[spc].fa=tr[f].fa; 69 tr[f].fa=spc; 70 tr[tr[f].ch[k]].fa=f; 71 return ; 72 } 73 void splay(int spc) 74 { 75 recal(spc); 76 while(!tr[spc].anc) 77 { 78 int f=tr[spc].fa; 79 if(tr[f].anc) 80 { 81 rotate(spc); 82 return ; 83 } 84 if(whc(spc)^whc(f))rotate(spc); 85 else rotate(f); 86 rotate(spc); 87 } 88 return ; 89 } 90 void access(int spc) 91 { 92 int lst=0; 93 while(spc) 94 { 95 splay(spc); 96 tr[rrr].anc=true; 97 tr[lst].anc=false; 98 rrr=lst; 99 lst=spc; 100 spc=tr[spc].fa; 101 } 102 return ; 103 } 104 void ADD(int from,int to,int cmd) 105 { 106 recal(from); 107 for(int i=1;i<=n;i++) 108 { 109 if(tr[from].val[i]) 110 { 111 add(to,i,tr[from].val[i]*cmd); 112 } 113 } 114 return ; 115 } 116 void link(int x,int f) 117 { 118 access(f); 119 splay(f); 120 splay(x); 121 ADD(x,f,1); 122 tr[x].fa=f; 123 return ; 124 } 125 void cut(int spc) 126 { 127 access(spc); 128 splay(spc); 129 int spc_=lll; 130 lll=tr[spc_].fa=0; 131 tr[spc_].anc=true; 132 splay(spc_); 133 ADD(spc,spc_,-1); 134 return ; 135 } 136 int decode(int c) 137 { 138 if(type)return (c xor lastans)%10; 139 return c; 140 } 141 int Insert(int fin,int no,int c) 142 { 143 if(s[fin].tranc[c]&&s[s[fin].tranc[c]].len==s[fin].len+1) 144 { 145 int spc=s[fin].tranc[c]; 146 access(spc); 147 splay(spc); 148 add(spc,no,1); 149 return spc; 150 } 151 int nwp,lsp,nwq,lsq,flag=0; 152 nwp=++siz;tr[nwp].val[no]=1; 153 s[nwp].len=s[fin].len+1; 154 for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)s[lsp].tranc[c]=nwp; 155 if(!lsp) 156 { 157 s[nwp].pre=1; 158 link(nwp,1); 159 }else{ 160 lsq=s[lsp].tranc[c]; 161 if(s[lsq].len==s[lsp].len+1) 162 { 163 s[nwp].pre=lsq; 164 link(nwp,lsq); 165 }else{ 166 if(s[nwp].len==s[lsp].len+1)flag=1; 167 nwq=++siz; 168 s[nwq]=s[lsq]; 169 s[nwq].len=s[lsp].len+1; 170 s[nwp].pre=s[lsq].pre=nwq; 171 cut(lsq); 172 link(nwq,s[nwq].pre); 173 link(nwp,nwq); 174 link(lsq,nwq); 175 while(s[lsp].tranc[c]==lsq) 176 { 177 s[lsp].tranc[c]=nwq; 178 lsp=s[lsp].pre; 179 } 180 } 181 } 182 sum+=s[nwp].len-s[s[nwp].pre].len; 183 if(flag)return nwq; 184 return nwp; 185 } 186 void init(void) 187 { 188 for(int i=1;i<=500000;i++)tr[i].anc=true; 189 siz=1; 190 return ; 191 } 192 int query(char *a) 193 { 194 int len=strlen(a+1); 195 int spc=1; 196 for(int i=1;i<=len;i++) 197 { 198 int c=a[i]-'0'; 199 spc=s[spc].tranc[c]; 200 if(!spc)return 0; 201 } 202 int ans=-1; 203 recal(spc); 204 for(int i=1;i<=n;i++) 205 ans=std::max(ans,tr[spc].val[i]); 206 return ans; 207 } 208 int main() 209 { 210 scanf("%d%d",&n,&type); 211 init(); 212 for(int i=1;i<=n;i++) 213 { 214 scanf("%s",str+1); 215 int len=strlen(str+1); 216 pos[i][0]=1; 217 for(int j=1;j<=len;j++) 218 pos[i][0]=Insert(pos[i][0],i,str[j]-'0'); 219 } 220 scanf("%d",&m); 221 for(int r=1;r<=m;r++) 222 { 223 for(int i=1;i<=n;i++)pos[i][r]=pos[i][r-1]; 224 int opt; 225 scanf("%d",&opt); 226 if(opt==1) 227 { 228 int x,y; 229 scanf("%d%d",&x,&y); 230 y=decode(y); 231 pos[x][r]=Insert(pos[x][r],x,y); 232 } 233 if(opt==2) 234 { 235 int x,y,z; 236 scanf("%d%d%d",&x,&y,&z); 237 int spc=pos[x][y]; 238 recal(spc); 239 lastans=tr[spc].val[z]; 240 printf("%d\n",lastans); 241 } 242 if(opt==3)printf("%lld\n",sum); 243 if(opt==4) 244 { 245 scanf("%s",str+1); 246 lastans=query(str); 247 printf("%d\n",lastans); 248 } 249 } 250 return 0; 251 }