#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
void precalc() {}
const int K = 26;
struct node {
  node *to[K];
  int cnt;
  node() : cnt() { memset(to, 0, sizeof(to)); }
};
const int maxn = 6e5 + 10;
int n;
int c[maxn];
char ch[maxn];
vector<int> to[maxn];
bool read() {
  if (scanf("%d", &n) < 1) {
    return false;
  }
  for (int i = 0; i < n; ++i) {
    scanf("%d", &c[i]);
  }
  for (int i = 0; i < n; ++i) {
    scanf(" %c ", &ch[i]);
  }
  for (int i = 0; i < n; ++i) {
    to[i].clear();
  }
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    a--, b--;
    to[a].push_back(b), to[b].push_back(a);
  }
  return true;
}
int cnts[maxn];
bool used[maxn];
node *r[maxn];
node *merge(node *a, node *b) {
  if (!a || !b) {
    return (a ? a : b);
  }
  for (int i = 0; i < K; ++i) {
    if (b->to[i]) {
      if (a->to[i]) {
        a->cnt -= a->to[i]->cnt;
      }
      a->to[i] = merge(a->to[i], b->to[i]);
      a->cnt += a->to[i]->cnt;
    }
  }
  return a;
}
void dfs(int v) {
  used[v] = true;
  r[v] = new node();
  r[v]->cnt = 1;
  for (auto u : to[v]) {
    if (used[u]) {
      continue;
    }
    dfs(u);
    int x = ch[u] - 'a';
    assert(0 <= x && x < K);
    if (r[v]->to[x]) {
      r[v]->cnt -= r[v]->to[x]->cnt;
    }
    r[v]->to[x] = merge(r[v]->to[x], r[u]);
    r[v]->cnt += r[v]->to[x]->cnt;
  }
  cnts[v] = r[v]->cnt;
}
void solve() {
  memset(used, 0, sizeof(used));
  dfs(0);
  int ans = -1, cnt = 0;
  for (int i = 0; i < n; ++i) {
    if (ans < cnts[i] + c[i]) {
      ans = cnts[i] + c[i];
      cnt = 0;
    }
    if (ans == cnts[i] + c[i]) {
      cnt++;
    }
  }
  printf("%d\n%d\n", ans, cnt);
}
int main() {
  srand(rdtsc());
  precalc();
  while (true) {
    if (!read()) {
      break;
    }
    solve();
  }
  return 0;
}
