trie合并的裸题...因为最多只有n个点,所以最多合并n次,复杂度$O(N*26)$。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=500010, inf=1e9;
struct poi{int too, pre;}e[maxn<<1];
struct tjm{int nxt[26], size;}tree[maxn];
int n, x, y, ans, cnt, tot;
int last[maxn], c[maxn];
char s[maxn];
inline void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
    while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
    k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void merge(int &x, int y)
{
    if(!x || !y) {x+=y; return;}
    tree[x].size=1;
    for(int i=0;i<26;i++)
        merge(tree[x].nxt[i], tree[y].nxt[i]), tree[x].size+=tree[tree[x].nxt[i]].size;
}
void dfs(int x, int fa)
{
    tree[x].size=1;
    for(int i=last[x], too;i;i=e[i].pre)
    if((too=e[i].too)!=fa)
    {
        dfs(too, x); int tmp=tree[tree[x].nxt[s[e[i].too]-'a']].size;
        merge(tree[x].nxt[s[e[i].too]-'a'], e[i].too);
        tree[x].size+=tree[tree[x].nxt[s[e[i].too]-'a']].size-tmp; 
    }
    if(tree[x].size+c[x]>ans) ans=tree[x].size+c[x], cnt=1;
    else if(tree[x].size+c[x]==ans) cnt++;
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(c[i]); scanf("%s", s+1);
    for(int i=1;i<n;i++) read(x), read(y), add(x, y), add(y, x);
    dfs(1, 0); printf("%d\n%d", ans, cnt);
}
View Code

相关文章: