bzoj4231回忆树
Posted paul-guderian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4231回忆树相关的知识,希望对你有一定的参考价值。
-
题解:
- 树上的串匹配,模式串的总长$|S|$,令$overline {S} $为$S$的反串;
- 对$S$和$overline {S} $分别建自动机
- $u -> v$可以分成三个部分去统计
- ①跨越了$lca(u, v)$的部分,长度不会超过$2|S|$,$kmp$暴力统计答案;
- ②$(u,lca)$上不跨越$lca$的部分,差分变成两个到根的询问;
- ②$(lca,v)$上不跨越$lca$的部分,差分变成两个到根的询问;
- $dfs$原树并记录走到两个自动机的节点$x / y$,$BIT$维护$fail$树的子树和:
- 进入时$add(x / y,1)$,回溯时$add(x / y,-1)$;
- ②在$overline {S} $里查,①在$S$里查即可处理所有询问;
- (突然发现似乎不用建两个自动机,直接建在一起就好了TAT所以别学大米饼丑陋的代码)
- 一个弱化版:bzoj3881,另外树剖$lca$常数小,好些,点分治常用$rmq$求$lca$;
-
1 #include<bits/stdc++.h> 2 #define rg register 3 #define il inline 4 using namespace std; 5 const int N=100010,M=300010; 6 int n,m,o=1,hd[N],Hd[N],O=1,tp[N],sz[N],sn[N],dfn[N],idx; 7 int q[N],head,tail,fa[N],f[N],pos[N],dep[N],ans[N]; 8 struct Edge{int v,nt,c;}E[N<<1]; 9 struct Qury{int p,x,y,nt;}Q[N<<2]; 10 char s[N],t[N],fm[N]; 11 il void adde(int u,int v,int c){ 12 E[o]=(Edge){v,hd[u],c};hd[u]=o++; 13 E[o]=(Edge){u,hd[v],c};hd[v]=o++; 14 } 15 il void addq(int u,int p,int x,int y){ 16 Q[O]=(Qury){p,x,y,Hd[u]};Hd[u]=O++; 17 } 18 void dfs1(int u,int F){ 19 sz[u]=1;sn[u]=0; 20 dep[u]=dep[fa[u]=F]+1; 21 for(rg int i=hd[u];i;i=E[i].nt){ 22 int v=E[i].v; 23 if(v==F)continue; 24 fm[v]=E[i].c+‘a‘; 25 dfs1(v,u); 26 sz[u]+=sz[v]; 27 if(sz[v]>sz[sn[u]])sn[u]=v; 28 } 29 } 30 void dfs2(int u,int T){ 31 dfn[pos[u]=++idx]=u;tp[u]=T; 32 if(sn[u])dfs2(sn[u],T); 33 for(rg int i=hd[u];i;i=E[i].nt){ 34 int v=E[i].v; 35 if(v==fa[u]||v==sn[u])continue; 36 dfs2(v,v); 37 } 38 } 39 il int go(int u,int d){ 40 int tu=tp[u]; 41 while(dep[u]-dep[tu]<d){ 42 d-=dep[u]-dep[tu]+1; 43 u=fa[tu],tu=tp[u]; 44 } 45 return dfn[pos[tu]+dep[u]-dep[tu]-d]; 46 } 47 il int lca(int u,int v){ 48 int tu=tp[u],tv=tp[v]; 49 while(tu!=tv)if(dep[tu]>dep[tv])u=fa[tu],tu=tp[u]; 50 else v=fa[tv],tv=tp[v]; 51 return dep[u]<dep[v]?u:v; 52 } 53 il int kmp(int x,int y,int z,int ls){ 54 int lt=0,tl=0,re=0; 55 while(dep[x]>dep[z])t[++lt]=fm[x],x=fa[x]; 56 tl=lt=lt+dep[y]-dep[z]; 57 while(dep[y]>dep[z])t[tl--]=fm[y],y=fa[y]; 58 if(lt<ls)return 0; 59 f[0]=f[1]=0; 60 for(rg int i=1,j=0;i<ls;f[++i]=j){ 61 while(j&&s[i+1]!=s[j+1])j=f[j]; 62 if(s[i+1]==s[j+1])j++; 63 } 64 for(rg int i=1,j=0;i<=lt;i++){ 65 while(j&&t[i]!=s[j+1])j=f[j]; 66 if(t[i]==s[j+1])j++; 67 if(j==ls)re++,j=f[j]; 68 } 69 return re; 70 } 71 struct AC{ 72 int cnt,fl[M],fa[M],st[M],ed[M],idx,c[M],ch[M][26],pos[N],hd[N],o; 73 struct Edge{int v,nt;}E[N]; 74 il void adde(int u,int v){E[o]=(Edge){v,hd[u]};hd[u]=o++;} 75 il void add(int x,int y){for(;x<=idx;x+=x&-x)c[x]+=y;} 76 il int ask(int x){int re=0;for(;x;x-=x&-x)re+=c[x];return re;} 77 il void ins(int cur,int l){ 78 int x=0; 79 for(int i=1,y;i<=l;i++){ 80 if(!ch[x][y=s[i]-‘a‘])ch[x][y]=++cnt; 81 x=ch[x][y]; 82 }pos[cur]=x; 83 } 84 il void dfs(int u){ 85 st[u]=++idx; 86 for(rg int i=hd[u];i;i=E[i].nt)dfs(E[i].v); 87 ed[u]=idx; 88 } 89 il void bfs(){ 90 o=1;head=tail=0; 91 for(int i=0;i<26;i++)if(ch[0][i]){ 92 q[++tail]=ch[0][i]; 93 adde(0,ch[0][i]); 94 } 95 while(head<tail){ 96 int u=q[++head]; 97 for(rg int i=0;i<26;i++){ 98 int&v=ch[u][i]; 99 if(!v){v=ch[fl[u]][i];continue;} 100 fl[v]=ch[fl[u]][i]; 101 q[++tail]=v; 102 adde(fl[v],v); 103 } 104 } 105 dfs(0); 106 } 107 il int que(int x){return ask(ed[pos[x]]) - ask(st[pos[x]]-1);} 108 }ac[2]; 109 void dfs3(int u,int y0,int y1){ 110 ac[0].add(ac[0].st[y0],1); 111 ac[1].add(ac[1].st[y1],1); 112 for(int i=Hd[u];i;i=Q[i].nt){ 113 ans[Q[i].x]+=ac[Q[i].p].que(Q[i].x)*Q[i].y; 114 } 115 for(int i=hd[u];i;i=E[i].nt){ 116 int v=E[i].v , c=E[i].c; 117 if(E[i].v==fa[u])continue; 118 dfs3(v,ac[0].ch[y0][c],ac[1].ch[y1][c]); 119 } 120 ac[0].add(ac[0].st[y0],-1); 121 ac[1].add(ac[1].st[y1],-1); 122 } 123 int main(){ 124 #ifndef ONLINE_JUDGE 125 freopen("bzoj4231.in","r",stdin); 126 freopen("bzoj4231.out","w",stdout); 127 #endif 128 scanf("%d%d",&n,&m); 129 for(rg int i=1;i<n;i++){ 130 int u,v; 131 scanf("%d%d%s",&u,&v,s+1); 132 adde(u,v,s[1]-‘a‘); 133 } 134 dfs1(1,0);dfs2(1,1); 135 for(rg int i=1;i<=m;i++){ 136 int u,v,w,l,t1,t2; 137 scanf("%d%d%s",&u,&v,s+1); 138 w=lca(u,v); 139 l=strlen(s+1); 140 t1=go(u,max(0,dep[u]-dep[w]-l+1)); 141 t2=go(v,max(0,dep[v]-dep[w]-l+1)); 142 ans[i]+=kmp(t1,t2,w,l); 143 ac[0].ins(i,l); 144 for(rg int j=1;j<=l>>1;j++)swap(s[j],s[l-j+1]); 145 ac[1].ins(i,l); 146 if(t1!=u)addq(u,1,i,1),addq(t1,1,i,-1); 147 if(t2!=v)addq(v,0,i,1),addq(t2,0,i,-1); 148 } 149 ac[0].bfs(); 150 ac[1].bfs(); 151 dfs3(1,0,0); 152 for(rg int i=1;i<=m;i++){printf("%d ",ans[i]);} 153 return 0; 154 }
$lca(q[i-1],q[i])$
以上是关于bzoj4231回忆树的主要内容,如果未能解决你的问题,请参考以下文章