#include <bits/stdc++.h>
using namespace std;
struct node {
  long long sm;
  node *ch[26];
  node() {
    sm = 1;
    for (int i = 0; i < 26; i++) ch[i] = NULL;
  }
};
void merge(node *t1, node *t2) {
  for (int i = 0; i < 26; i++) {
    if (t1->ch[i] != NULL && t2->ch[i] != NULL)
      merge(t1->ch[i], t2->ch[i]);
    else if (t1->ch[i] == NULL && t2->ch[i] != NULL) {
      t1->ch[i] = t2->ch[i];
    }
  }
  long long sm = 1;
  for (int i = 0; i < 26; i++) {
    if (t1->ch[i]) {
      sm += t1->ch[i]->sm;
    }
  }
  t1->sm = sm;
}
struct cmp {
  bool operator()(const node *a, const node *b) { return a->sm > b->sm; }
};
string S;
int C[300005];
long long dif[300005];
vector<int> tr[300005];
node *dfs(int i, int p) {
  priority_queue<node *, vector<node *>, cmp> tomerge[26];
  for (int j = 0; j < tr[i].size(); j++) {
    if (tr[i][j] == p) continue;
    tomerge[S[tr[i][j]] - 'a'].push(dfs(tr[i][j], i));
  }
  node *trie = new node;
  for (int i = 0; i < 26; i++) {
    while (tomerge[i].size() > 1) {
      node *a = tomerge[i].top();
      tomerge[i].pop();
      node *b = tomerge[i].top();
      tomerge[i].pop();
      merge(b, a);
      tomerge[i].push(b);
    }
    if (!tomerge[i].empty()) {
      trie->ch[i] = tomerge[i].top();
      trie->sm += trie->ch[i]->sm;
    }
  }
  dif[i] = trie->sm;
  return trie;
}
int main() {
  int n;
  scanf("%d", &n);
  char s[300005];
  for (int i = 0; i < n; i++) scanf("%d", C + i);
  scanf("%s", s);
  S = string(s);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    u--;
    v--;
    tr[u].push_back(v);
    tr[v].push_back(u);
  }
  dfs(0, -1);
  int cnt = 0;
  long long mx = 0;
  for (int i = 0; i < n; i++) {
    if (dif[i] + C[i] > mx) {
      cnt = 1;
      mx = dif[i] + C[i];
    } else if (dif[i] + C[i] == mx)
      cnt++;
  }
  printf("%I64d\n%d\n", mx, cnt);
}
