给每个子树存一个 size 因为 我们只需要每个字符出现一次 所以如果x 或者 y一个没有的话才能返回 不然的话 就会重复
#include<iostream>
#include<cstring>
#define x first
#define y second
using namespace std;
const int N = (3e5 + 10) * 2,M = N * 2;
typedef pair<int,int> PII;
typedef long long ll;
int a[N];char b[N];
int head[N],to[M],last[M],cnt;
void add(int a,int b){
to[++cnt] = b;
last[cnt] = head[a];
head[a] = cnt;
}
int tree[N][30];
int v[N],T[N];
int ans;
int insert(int p,char a){
if(!p) p = ++ans;
++ans;
for(int i = 0; i <= 25; i++){
tree[ans][i] = tree[p][i];
tree[p][i] = 0;
}
v[ans] += v[p];
tree[p][a - 'a'] = ans;
v[ans]++;
v[p] = v[ans];
return p;
}
PII merge(int x,int y){
if(!x) return {y,v[y]};
if(!y) return {x,v[x]};
for(int i = 0; i <= 25; i++){
int d = v[tree[x][i]];
PII p = merge(tree[x][i],tree[y][i]);
if(p.x == tree[y][i]) v[x] += p.y;
if(p.x == tree[x][i]) v[x] -= d,v[x] += p.y;
tree[x][i] = p.x;
}
return {x,v[x]};
}
ll maxn = 0,has = 0;
void dfs(int x,int pre){
int now = 0;
for(int i = head[x]; i != -1; i = last[i]){
int j = to[i];
if(j == pre) continue;
dfs(j,x);
if(!now) now = j;
else{
PII d = merge(T[now],T[j]);
T[now] = d.x;
}
}
T[0] = 0;
T[x] = insert(T[now],b[x]);
if(maxn < v[T[x]] + a[x]){
maxn = v[T[x]] + a[x];
has = 1;
}else if(maxn == v[T[x]] + a[x]) has++;
}
int main(){
int n;
cin >> n;
memset(head,-1,sizeof head);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
scanf("%s",b + 1);
for(int i = 1; i <= n - 1; i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,0);
cout << maxn << endl;
cout << has << endl;
return 0;
}