[BZOJ4477][JSOI2015]字符串树 可持久化Trie树

首先考虑树上差分, x y 的答案可以差分成 x 到根+ y 到根- 2lca(x,y) 到根的答案。
考虑如何维护每个点到根路径上的所有字符串,想到Trie树,又因为每个点和其父亲只相差一个串,每个串长又不超过 10 ,所以考虑用可持久化Trie树,这样树上节点就不会超过所有串总长。树上每个点记录 size 表示在其子树中有多少个串。
每次询问的时候只要在Trie上跑完询问串,当前点的 size 就是答案。
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100010;
int n,q,sz[maxn*10],trie[maxn*10][26],rt[maxn],fa[maxn][20],d[maxn],tot;
char sc[15];
struct edge
{
    int t,l;
    char s[15];
    edge *next;
}*con[maxn];
void ins(int x,int y)
{
    edge *p=new edge;
    p->t=y;
    p->l=strlen(sc+1);
    for(int i=1;i<=p->l;i++)
        p->s[i]=sc[i];
    p->next=con[x];
    con[x]=p;
}
void build(int now,int lst,edge *p,int d)
{
    sz[now]=sz[lst]+1;
    if(d>p->l) {return ;}
    for(int c=0;c<=25;c++)
        if(c!=p->s[d]-'a') trie[now][c]=trie[lst][c];
    trie[now][p->s[d]-'a']=++tot;
    build(tot,trie[lst][p->s[d]-'a'],p,d+1);
}
void init()
{
    for(int k=1;(1<<k)<=n;k++)
        for(int i=1;i<=n;i++)
            fa[i][k]=fa[fa[i][k-1]][k-1];
}
int lca(int x,int y)
{
    if(d[x]<d[y]) swap(x,y);
    for(int k=19;k>=0;k--) if(d[fa[x][k]]>=d[y]) x=fa[x][k];
    for(int k=19;k>=0;k--) if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
    return (x==y?x:fa[x][0]);
}
void dfs(int v)
{
    d[v]=d[fa[v][0]]+1;
    for(edge *p=con[v];p;p=p->next)
        if(p->t!=fa[v][0]) 
        {
            rt[p->t]=++tot;
            build(rt[p->t],rt[v],p,1);
            fa[p->t][0]=v;
            dfs(p->t);
        }
}
int qry(int p)
{
    int len=strlen(sc+1);
    for(int i=1;i<=len;i++)
        p=trie[p][sc[i]-'a'];
    return sz[p];   
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int x,y,len;
        scanf("%d%d%s",&x,&y,sc+1);
        ins(x,y);
        ins(y,x);
    }
    rt[1]=tot=1;    
    dfs(1);
    init();
    scanf("%d",&q);
    while(q--)
    {
        int x,y;
        scanf("%d%d%s",&x,&y,sc+1);
        printf("%d\n",qry(rt[x])+qry(rt[y])-2*qry(rt[lca(x,y)]));
    } 
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/DOFYPXY/article/details/78837701
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞