#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <cassert>
#include <ctime>
#include <cstdlib>

typedef unsigned long long ull;

const ull mod = (ull(1) << 61) - 1;
    
inline ull add(ull a, ull b) {
    return (a += b) < mod ? a : a - mod;
}
    
inline ull sub(ull a, ull b) {
    return (a -= b) < mod ? a : a + mod;
}

inline ull mul(ull a, ull b) {
    ull l1 = (uint32_t)a, h1 = a >> 32, l2 = (uint32_t)b, h2 = b >> 32;
    ull l = l1*l2, m = l1*h2 + l2*h1, h = h1*h2;
    ull ret = (l & mod) + (l >> 61) + (h << 3) + (m >> 29) + (m << 35 >> 3) + 1;
    ret = (ret & mod) + (ret >> 61);
    ret = (ret & mod) + (ret >> 61);
    return ret-1;
}

std::vector<int> fast(int n, std::vector<std::pair<int,char>> input) {
    const int NMAX = (int)5e5, PMAX = 20;
    std::vector<int> answ(1+n), len(1+n);
    std::vector<std::vector<int>> edges(1+n);
    std::vector<char> cost(1+n); // cost from child to parent
    static int parent[PMAX][1+NMAX];
    static ull hashes[PMAX][1+NMAX];
    // Input:
    for (int u = 2; u <= n; ++u) {
        int p = input[u].first; 
        cost[u] = input[u].second;
        edges[p].push_back(u);
        edges[u].push_back(p);
        parent[0][u] = p;
        hashes[0][u] = cost[u];
    }
    // Precalc powers of base:
    const ull BASE = (int)1e9+7;
    std::vector<ull> pow{1};
    while ((int)pow.size() < NMAX) {
        pow.push_back(mul(pow.back(), BASE));
    }
    // Precalc parents and hashes:
    for (int p = 1; p < PMAX; ++p) {
        for (int u = 1; u <= n; ++u) {
            int v = parent[p-1][u];
            if (v == 0) continue;
            parent[p][u] = parent[p-1][v];
            hashes[p][u] = add(mul(hashes[p-1][v], pow[1<<(p-1)]), hashes[p-1][u]);
        }
    }
    // Get parent of vertex u with `nSteps` steps up:
    std::function<int(int,int)> get_parent = [&](int u, int nSteps) {
        for (int p = PMAX-1; p >= 0; --p) {
            if (((nSteps >> p) & 1) == 1) {
                u = parent[p][u];
            }
        }
        return u;
    };
    // Get hash from vertex u with `nSteps` steps up:
    std::function<ull(int,int)> get_hash = [&](int u, int nSteps) {
        int sum = 0; ull hash = 0;
        for (int p = PMAX-1; p >= 0; --p) {
            if (((nSteps >> p) & 1) == 1) {
                hash = add(hash, mul(hashes[p][u], pow[sum]));
                sum += (1 << p);
                u = parent[p][u];
            }
        }
        return hash;
    };
    // DFS:
    std::function<void(int,int)> visit = [&](int u, int p) {
        int max = -1, r = u;
        for (int v : edges[u]) {
            if (p == v) continue;
            visit(v,u);
            if (len[v] > max) {
                max = len[v];
                r = v;
            } else if (len[v] == max) {
                // find first not equal symbol
                int low = 0, high = max+2;
                while (high - low > 1) {
                    int mid = (low + high) / 2;
                    ull hash1 = get_hash(get_parent(answ[v], max+1-mid), mid);
                    ull hash2 = get_hash(get_parent(answ[r], max+1-mid), mid);
                    if (hash1 == hash2) {
                        low = mid;
                    } else {
                        high = mid;
                    }
                }
                if (low < max+1) {
                    int pv = get_parent(answ[v], max-low);
                    int pr = get_parent(answ[r], max-low);
                    assert(cost[pv] != cost[pr]);
                    if (cost[pv] > cost[pr]) {
                        r = v;
                    }
                } else if (answ[v] < answ[r]) {
                    r = v;
                }
            }
        }
        len[u] = max+1;
        answ[u] = (r == u) ? r : answ[r]; 
    };
    visit(1,0); // Run dfs
    // Return answer:
    for (int u = 1; u <= n; ++u) {
        answ[u] = (answ[u] == u) ? 0 : answ[u];
    }
    return answ;
}

std::vector<int> slow(int n, std::vector<std::pair<int, char>> input) {
    std::vector<char> cost(1+n);
    std::vector<int> answ(1+n);
    std::vector<std::vector<int>> edges(1+n);
    // Input:
    for (int u = 2; u <= n; ++u) {
        int p = input[u].first; 
        cost[u] = input[u].second;
        edges[p].push_back(u);
        edges[u].push_back(p);
    }
    std::function<std::string(int,int)> visit = [&](int u, int p) {
        std::string best; int r = u;
        for (int v : edges[u]) {
            if (v == p) continue;
            auto temp = cost[v] + visit(v, u);
            if (temp.size() > best.size()) {
                best = temp;
                r = v;
            } else if (temp.size() == best.size()) {
                if (temp > best || (temp == best && answ[v] < answ[r])) {
                    best = temp;
                    r = v;
                }
            }
        }
        answ[u] = (r == u) ? r : answ[r];
        return best;
    };
    visit(1,0);
    for (int u = 1; u <= n; ++u) {
        if (answ[u] == u) answ[u] = 0;
    }
    return answ;
}

std::vector<std::pair<int, char>> input(int& n) {
    scanf("%d", &n);
    std::vector<std::pair<int, char>> answ(1+n);
    for (int u = 2; u <= n; ++u) {
        int p; char c;
        scanf("%d %c", &p, &c);
        answ[u] = std::make_pair(p,c);
    }
    return answ;
}

int main() {
    int n;
    auto in = input(n);
    auto answ1 = fast(n, in);
    for (int u = 1; u <= n; ++u) {
        printf("%d\n", answ1[u]);
    }
    return 0;
}