#include <bits/stdc++.h>
using namespace std;

const int ALPHABET_SIZE = 26;
int to_index(char c) { return c-'a'; }

struct trie_node {
    bool word_end;
    int size;
    trie_node *son[ALPHABET_SIZE];
    trie_node() { word_end=false; size=0; memset(son,0,sizeof(son)); }
};

trie_node* grow_upwards(trie_node* root, char c) {
    if (!root) root = new trie_node();
    trie_node *new_root = new trie_node();
    new_root->son[ to_index(c) ] = root;
    root->word_end = true;
    ++(root->size);
    new_root->size = root->size;
    return new_root;
}

trie_node* merge(trie_node* left, trie_node* right) {
    if (!left) return right;
    if (!right) return left;
    left->size = 0;
    for (int c=0; c<ALPHABET_SIZE; ++c) {
        left->son[c] = merge( left->son[c], right->son[c] );
        if (left->son[c]) left->size += left->son[c]->size;
    }
    left->word_end |= right->word_end;
    if (left->word_end) ++(left->size);
    return left;
}

vector< vector<int> > T;
string S;
vector<int> C;
vector<bool> visited;

trie_node* dfs(int kde) {
    visited[kde] = true;
    vector<trie_node*> deti;
    for (int kam : T[kde]) if (!visited[kam]) deti.push_back( dfs(kam) );
    trie_node *root = grow_upwards( NULL, S[kde] );
    for (auto &x : deti) {
        x = grow_upwards( x, S[kde] );
        root = merge( root, x );
    }
    C[kde] += root->size;
    return root;
}

int main() {
    int N;
    cin >> N;
    C.resize(N);
    for (int &c:C) cin >> c;
    cin >> S;
    T.resize(N);
    for (int n=0; n<N-1; ++n) {
        int a, b; cin >> a >> b; --a; --b;
        T[a].push_back(b);
        T[b].push_back(a);
    }
    visited.resize(N,false);
    dfs(0);
    int maxval = *max_element( C.begin(), C.end() );
    int maxcnt = 0;
    for (int &c:C) if (c==maxval) ++maxcnt;
    cout << maxval << endl << maxcnt << endl;
}