【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\n",ans[i]);}
      153     return 0;
      154 }
      bzoj4231

       

 

 

$lca(q[i-1],q[i])$

posted @ 2019-01-09 07:35  大米饼  阅读(346)  评论(0编辑  收藏  举报