#include <bits/stdc++.h>

using namespace std;

#define sz(a) int(a.size())

struct Dis {
	int depth, xor_l;
	Dis (int depth = 0, int xor_l = 0) : depth(depth), xor_l(xor_l) {}
	Dis operator +(const int &x) const {
		return Dis(depth+1, xor_l^(1<<x));
	}
};

const int MAX_N = 1<<19;

vector <int> cn [MAX_N], dn[MAX_N];
vector <Dis> D;
int ss [MAX_N], in[MAX_N], out[MAX_N];

vector <int> eTour;
void preComp (int u) {
	ss[u] = 1;
	in[u] = sz(eTour);
	eTour.push_back(u);
	for (int i = 0; i < sz(cn[u]); i++) {
		int v = cn[u][i];
		D[v] = D[u] + dn[u][i];
		preComp(v);
		ss[u] += ss[v];
	}
	out[u] = sz(eTour);
}

multiset <int> dXor [1<<22];

vector <int> ans;
void dfs(int u, bool keep){
	int mxSS = -1, mxChild = -1;

	for (int v : cn[u])  {
		if (ss[v] > mxSS) mxSS = ss[v], mxChild = v;
	}

	for (int v : cn[u]) {
		if (v != mxChild) dfs(v, 0);
		ans[u] = max(ans[u], ans[v]);
	}

	if(mxChild != -1) {
		dfs(mxChild, 1);
		ans[u] = max(ans[u], ans[mxChild]);
	}

	int best = 0;
	for(int v : cn[u]) {
		if (v != mxChild) {
			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];

				auto &ms = dXor[D[t].xor_l];
				if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);

				for (int l = 0; l < 22; l++) {
					auto &ms = dXor[D[t].xor_l^(1<<l)];
					if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);
				}
			}

			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];
				dXor[D[t].xor_l].insert(D[t].depth);
			}
		}
	}

	auto &ms = dXor[D[u].xor_l];
	if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);

	for (int l = 0; l < 22; l++) {
		auto &ms = dXor[D[u].xor_l^(1<<l)];
		if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);
	}

	ans[u] = max(ans[u], best);
	dXor[D[u].xor_l].insert(D[u].depth);

	if (!keep) {
		for (int x = in[u]; x < out[u]; x++) {
			int t = eTour[x];
			auto &toErase = dXor[D[t].xor_l];
			toErase.erase(toErase.find(D[t].depth));
		}
	}
}

char c[2];
int main() {

	int n;
	scanf("%d", &n);
	D.resize(n);
	ans.resize(n);

	for (int v = 1; v < n; v++) {
		int u;
		scanf("%d%s", &u, c);
		u--;

		cn[u].push_back(v);
		dn[u].push_back(c[0]-'a');
	}

	preComp(0);
	dfs(0, 1);

	for (int t : ans) printf("%d ", t);
}


#include <bits/stdc++.h>

using namespace std;

#define sz(a) int(a.size())

struct Dis {
	int depth, xor_l;
	Dis (int depth = 0, int xor_l = 0) : depth(depth), xor_l(xor_l) {}
	Dis operator +(const int &x) const {
		Dis ret = *this;
		ret.depth++;
		ret.xor_l ^= 1<<x;
		return ret;
	}
};

const int MAX_N = 1<<19;

vector <int> cn [MAX_N], dn[MAX_N];
vector <Dis> D;
int ss [MAX_N], in[MAX_N], out[MAX_N];

vector <int> eTour;
void preComp (int u) {
	ss[u] = 1;
	in[u] = sz(eTour);
	eTour.push_back(u);
	for (int i = 0; i < sz(cn[u]); i++) {
		int v = cn[u][i];
		D[v] = D[u] + dn[u][i];
		preComp(v);
		ss[u] += ss[v];
	}
	out[u] = sz(eTour);
}

multiset <int> dXor [1<<22];

vector <int> ans;
void dfs(int u, bool keep){
	int mxSS = -1, mxChild = -1;

	for (int v : cn[u])  {
		if (ss[v] > mxSS) mxSS = ss[v], mxChild = v;
	}

	for (int v : cn[u]) {
		if (v != mxChild) dfs(v, 0);
	}

	if(mxChild != -1) dfs(mxChild, 1);

	int best = 0;
	for(int v : cn[u]) {
		if (v != mxChild) {
			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];

				auto &ms = dXor[D[t].xor_l];
				if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);

				for (int l = 0; l < 22; l++) {
					ms = dXor[D[t].xor_l^(1<<l)];
					if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);
				}
			}

			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];
				dXor[D[t].xor_l].insert(D[t].depth);
			}
		}
	}

	auto &ms = dXor[D[u].xor_l];
	if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);

	for (int l = 0; l < 22; l++) {
		ms = dXor[D[u].xor_l^(1<<l)];
		if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);
	}

	ans[u] = best;
	dXor[D[u].xor_l].insert(D[u].depth);

	if (!keep) {
		for (int x = in[u]; x < out[u]; x++) {
			int t = eTour[x];
			auto &toErase = dXor[D[t].xor_l];
			toErase.erase(toErase.find(D[t].depth));
		}
	}
}

char c[2];
int main() {

	int n;
	scanf("%d", &n);
	D.resize(n);
	ans.resize(n);

	for (int v = 1; v < n; v++) {
		int u;
		scanf("%d%s", &u, c);
		u--;

		cn[u].push_back(v);
		dn[u].push_back(c[0]-'a');
	}

	preComp(0);

	dfs(0, 1);

	for (int t : ans) printf("%d ", t);
}


#include <bits/stdc++.h>

using namespace std;

#define sz(a) int(a.size())

struct Dis {
	int depth, xor_l;
	Dis (int depth = 0, int xor_l = 0) : depth(depth), xor_l(xor_l) {}
	Dis operator +(const int &x) const {
		Dis ret = *this;
		ret.depth++;
		ret.xor_l ^= 1<<x;
		return ret;
	}
};

const int MAX_N = 1<<19;

vector <int> cn [MAX_N], dn[MAX_N];
vector <Dis> D;
int ss [MAX_N], in[MAX_N], out[MAX_N];

vector <int> eTour;
void preComp (int u) {
	ss[u] = 1;
	in[u] = sz(eTour);
	eTour.push_back(u);
	for (int i = 0; i < sz(cn[u]); i++) {
		int v = cn[u][i];
		D[v] = D[u] + dn[u][i];
		preComp(v);
		ss[u] += ss[v];
	}
	out[u] = sz(eTour);
}

multiset <int> dXor [1<<22];

vector <int> ans;
void dfs(int u, bool keep){
	int mxSS = -1, mxChild = -1;

	for (int v : cn[u])  {
		if (ss[v] > mxSS) mxSS = ss[v], mxChild = v;
	}

	for (int v : cn[u]) {
		if (v != mxChild) dfs(v, 0);
		ans[u] = max(ans[u], ans[v]);
	}

	if(mxChild != -1) {
		dfs(mxChild, 1);
		ans[u] = max(ans[u], ans[mxChild]);
	}

	int best = 0;
	for(int v : cn[u]) {
		if (v != mxChild) {
			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];

				auto &ms = dXor[D[t].xor_l];
				if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);

				for (int l = 0; l < 22; l++) {
					ms = dXor[D[t].xor_l^(1<<l)];
					if (!ms.empty()) best = max(best, *rbegin(ms) + D[t].depth - 2*D[u].depth);
				}
			}

			for (int x = in[v]; x < out[v]; x++) {
				int t = eTour[x];
				dXor[D[t].xor_l].insert(D[t].depth);
			}
		}
	}

	auto &ms = dXor[D[u].xor_l];
	if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);

	for (int l = 0; l < 22; l++) {
		ms = dXor[D[u].xor_l^(1<<l)];
		if (!ms.empty()) best = max(best, *rbegin(ms) - D[u].depth);
	}

	ans[u] = max(ans[u], best);
	dXor[D[u].xor_l].insert(D[u].depth);

	if (!keep) {
		for (int x = in[u]; x < out[u]; x++) {
			int t = eTour[x];
			auto &toErase = dXor[D[t].xor_l];
			toErase.erase(toErase.find(D[t].depth));
		}
	}
}

char c[2];
int main() {

	int n;
	scanf("%d", &n);
	D.resize(n);
	ans.resize(n);

	for (int v = 1; v < n; v++) {
		int u;
		scanf("%d%s", &u, c);
		u--;

		cn[u].push_back(v);
		dn[u].push_back(c[0]-'a');
	}

	preComp(0);

	dfs(0, 1);

	for (int t : ans) printf("%d ", t);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5e5 + 5;
const int MAXM = (1 << 22) + 5;
const int INF = 0x3f3f3f3f;
#define DEBUG(x) cout << (x) << '\n'
#define fi first
#define se second

int n, a[MAXN], dep[MAXN], son[MAXN], siz[MAXN], f[MAXM], ret[MAXN];
vector<int> G[MAXN];
void dfs1(int u, int fa){
    siz[u] = 1, dep[u] = dep[fa] + 1, a[u] ^= a[fa];
    for(int& v : G[u]){
        dfs1(v, u); siz[u] += siz[v];
        if(siz[son[u]] < siz[v]) son[u] = v;
    }
}
void dfs3(int u, int p){
    ret[p] = max(ret[p], dep[u] + f[a[u]]);
    for(int i = 0; i < 22; i++)
        ret[p] = max(ret[p], dep[u] + f[a[u]^(1<<i)]);
    for(int& v : G[u]) dfs3(v, p);
}
void dfs4(int u){
    f[a[u]] = max(f[a[u]], dep[u]);
    for(int& v : G[u]) dfs4(v);
}
void dfs5(int u){
    f[a[u]] = -INF;
    for(int& v : G[u]) dfs5(v);
}
void dfs2(int u, bool I){
    for(int& v : G[u])
        if(v != son[u]) dfs2(v, 0);
    if(son[u]) dfs2(son[u], 1);
    for(int& v : G[u]) if(v != son[u])
        dfs3(v, u), dfs4(v);
    f[a[u]] = max(f[a[u]], dep[u]);
    ret[u] = max(ret[u], dep[u] + f[a[u]]);
    for(int i = 0; i < 22; i++)
        ret[u] = max(ret[u], dep[u] + f[a[u]^(1<<i)]);
    ret[u] -= dep[u] * 2;
    for(int& v : G[u]) ret[u] = max(ret[u], ret[v]);
    if(!I) dfs5(u);
}
void run(){
    cin >> n; char ch;
    for(int v = 2, u; v <= n; v++){
        cin >> u >> ch;
        G[u].push_back(v);
        a[v] = 1 << (ch - 'a');
    }
    memset(f, -62, sizeof f);
    dfs1(1, 0); dfs2(1, 0);
    for(int i = 1; i <= n; i++) cout << ret[i] << ' ';
}
int main(){
#ifdef Irene
    freopen("in.txt", "r", stdin);
#endif // Irene
    ios::sync_with_stdio(false);

    run(); return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 5e5 + 5;
const int MAXM = (1 << 22) + 5;
const int INF = 0x3f3f3f3f;
#define DEBUG(x) cout << (x) << '\n'
#define fi first
#define se second

int n, a[MAXN], dep[MAXN], son[MAXN], siz[MAXN], f[MAXM], ret[MAXN];
vector<int> G[MAXN];
void dfs1(int u, int fa){
    siz[u] = 1, dep[u] = dep[fa] + 1, a[u] ^= a[fa];
    for(int& v : G[u]){
        dfs1(v, u); siz[u] += siz[v];
        if(siz[son[u]] < siz[v]) son[u] = v;
    }
}
void dfs3(int u, int p){
    ret[p] = max(ret[p], dep[u] + f[a[u]]);
    for(int i = 0; i < 22; i++)
        ret[p] = max(ret[p], dep[u] + f[a[u]^(1<<i)]);
    for(int& v : G[u]) dfs3(v, p);
}
void dfs4(int u){
    f[a[u]] = max(f[a[u]], dep[u]);
    for(int& v : G[u]) dfs4(v);
}
void dfs5(int u){
    f[a[u]] = -INF;
    for(int& v : G[u]) dfs5(v);
}
void dfs2(int u, bool I){
    for(int& v : G[u])
        if(v != son[u]) dfs2(v, 0);
    if(son[u]) dfs2(son[u], 1);
    for(int& v : G[u]) if(v != son[u])
        dfs3(v, u), dfs4(v);
    f[a[u]] = max(f[a[u]], dep[u]);
    ret[u] = max(ret[u], dep[u] + f[a[u]]);
    for(int i = 0; i < 22; i++)
        ret[u] = max(ret[u], dep[u] + f[a[u]^(1<<i)]);
    ret[u] -= dep[u] * 2;
    for(int& v : G[u]) ret[u] = max(ret[u], ret[v]);
    if(!I) dfs5(u);
}
void run(){
    cin >> n;
    char ch; int p;
    for(int v = 2, u; v <= n; v++){
        cin >> u >> ch;
        G[u].push_back(v);
        a[v] = 1 << (ch - 'a');
    }
    dfs1(1, 0); dfs2(1, 0);
    for(int i = 1; i <= n; i++) cout << ret[i] << ' ';
}
int main(){
#ifdef Irene
    freopen("in.txt", "r", stdin);
#endif // Irene
    ios::sync_with_stdio(false);

    run(); return 0;
}


// 模板dsu on tree
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=5e5+10;
struct Edge{
	int go,next;
	char c;
}e[2*N];
int head[N],tot,son[N],sz[N],w[N];
int ans[N]; //Son是统计答案点的重儿子
//一般题目都会用到的数组，因为要离线统计每个节点答案，所以基本都用ans数组
void add(int x,int y,char c){
	e[++tot].go=y;
	e[tot].c=c;
	e[tot].next=head[x];
	head[x]=tot;
}
void get_son(int x,int f){  //预处理重儿子
	son[x]=0;sz[x]=1;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f)continue;
		get_son(v,x);
		if(sz[v]>sz[son[x]])son[x]=v,w[x]=e[i].c-'a';
		sz[x]+=sz[v];
	}
}
map<int,int>mp; //26个字母的奇偶对应长度
pair<int,int>q[N];
int r,xz,xl=-N;
void cal(int x,int st,int d){   //统计答案函数，因题而异
	q[++r]=make_pair(st^xz,d-xl);
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		int c=e[i].c-'a';
		cal(v,st^(1<<c),d+1);
	}
}
void pr(int x){
	for(int i=0;i<26;i++){
		if(x&(1<<i))cout<<(char)(i+'a');
	}
}
void debug(int x){
	cout<<x<<"  :";
	for(auto it:mp){
		if(it.second)pr(it.first^xz),cout<<"  "<<it.second<<endl;
	}
	cout<<endl;
}
void dfs(int x,int f,int del){  //按顺序调用统计答案函数
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f||v==son[x])continue;
		dfs(v,x,1);
	}
	if(son[x])dfs(son[x],x,0),mp[xz]=max(mp[xz],-xl),xz^=(1<<w[x]),xl++;
	//cout<<x<<"  "<<son[x]<<endl;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go,c=e[i].c-'a';
		if(v==son[x]||v==f)continue;
		r=0;cal(v,1<<c,1);
		for(int j=1;j<=r;j++){
			int s=q[j].first,len=q[j].second;
			if(mp.find(s)!=mp.end())ans[x]=max(ans[x],mp[s]+len+2*xl);
			for(int k=0;k<26;k++)
				if(mp.find(s^(1<<k))!=mp.end())ans[x]=max(ans[x],mp[s^(1<<k)]+len+2*xl);
		}
		for(int j=1;j<=r;j++)mp[q[j].first]=max(mp[q[j].first],q[j].second);
	}
	ans[x]=max(ans[x],mp[xz]+xl);
	for(int k=0;k<26;k++)ans[x]=max(ans[x],mp[xz^(1<<k)]+xl);
	//debug(x);
	if(del)mp.clear(),xz=0,xl=-N;
}
void dfs2(int x){
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		dfs2(v);
		ans[x]=max(ans[x],ans[v]);
	}
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
    	int p;
    	char tc[2];
    	scanf("%d%s",&p,tc);
    	add(p,i,tc[0]);
	}
	get_son(1,0);dfs(1,0,1);dfs2(1);
	for(int i=1;i<=n;i++)printf("%d%c",ans[i],(i==n)?'\n':' ');
	return 0;
}


// 模板dsu on tree
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=5e5+10;
struct Edge{
	int go,next;
	char c;
}e[N];
int head[N],tot,son[N],sz[N],w[N];
int ans[N]; //Son是统计答案点的重儿子
//一般题目都会用到的数组，因为要离线统计每个节点答案，所以基本都用ans数组
inline void add(int x,int y,char c){
	e[++tot].go=y;
	e[tot].c=c;
	e[tot].next=head[x];
	head[x]=tot;
}
inline void get_son(int x,int f){  //预处理重儿子
	son[x]=0;sz[x]=1;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f)continue;
		get_son(v,x);
		if(sz[v]>sz[son[x]])son[x]=v,w[x]=e[i].c-'a';
		sz[x]+=sz[v];
	}
}
unordered_map<int,int>mp; //26个字母的奇偶对应长度
pair<int,int>q[N];
int r,xz,xl=-N;
inline void cal(int x,int st,int d){   //统计答案函数，因题而异
	q[++r]=make_pair(st^xz,d-xl);
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		int c=e[i].c-'a';
		cal(v,st^(1<<c),d+1);
	}
}
void pr(int x){
	for(int i=0;i<26;i++){
		if(x&(1<<i))cout<<(char)(i+'a');
	}
}
void debug(int x){
	cout<<x<<"  :";
	for(auto it:mp){
		if(it.second)pr(it.first^xz),cout<<"  "<<it.second<<endl;
	}
	cout<<endl;
}
inline void dfs(int x,int f,int del){  //按顺序调用统计答案函数
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f||v==son[x])continue;
		dfs(v,x,1);
	}
	if(son[x])dfs(son[x],x,0),mp[xz]=max(mp[xz],-xl),xz^=(1<<w[x]),xl++;
	//cout<<x<<"  "<<son[x]<<endl;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go,c=e[i].c-'a';
		if(v==son[x]||v==f)continue;
		r=0;cal(v,1<<c,1);
		for(int j=1;j<=r;j++){
			int s=q[j].first,len=q[j].second;
			if(mp[s]>-xl)ans[x]=max(ans[x],mp[s]+len+2*xl);
			for(int k=0;k<26;k++)
				if(mp[s^(1<<k)]>-xl)ans[x]=max(ans[x],mp[s^(1<<k)]+len+2*xl);
		}
		for(int j=1;j<=r;j++)mp[q[j].first]=max(mp[q[j].first],q[j].second);
	}
	ans[x]=max(ans[x],mp[xz]+xl);
	for(int k=0;k<26;k++)ans[x]=max(ans[x],mp[xz^(1<<k)]+xl);
	//debug(x);
	if(del)mp.clear(),xz=0,xl=-N;
}
inline void dfs2(int x){
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		dfs2(v);
		ans[x]=max(ans[x],ans[v]);
	}
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
    	int p;
    	char tc[2];
    	scanf("%d%s",&p,tc);
    	add(p,i,tc[0]);
	}
	get_son(1,0);dfs(1,0,0);dfs2(1);
	for(int i=1;i<=n;i++)printf("%d%c",ans[i],(i==n)?'\n':' ');
	return 0;
}


// 模板dsu on tree
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=5e5+10;
struct Edge{
	int go,next;
	char c;
}e[N];
int head[N],tot,son[N],sz[N],w[N];
int ans[N]; //Son是统计答案点的重儿子
//一般题目都会用到的数组，因为要离线统计每个节点答案，所以基本都用ans数组
inline void add(int x,int y,char c){
	e[++tot].go=y;
	e[tot].c=c;
	e[tot].next=head[x];
	head[x]=tot;
}
inline void get_son(int x,int f){  //预处理重儿子
	son[x]=0;sz[x]=1;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f)continue;
		get_son(v,x);
		if(sz[v]>sz[son[x]])son[x]=v,w[x]=e[i].c-'a';
		sz[x]+=sz[v];
	}
}
int mp[1<<23]; //26个字母的奇偶对应长度
pair<int,int>q[N];
int r,xz,xl=-N;
inline void cal(int x,int st,int d){   //统计答案函数，因题而异
	q[++r]=make_pair(st^xz,d-xl);
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		int c=e[i].c-'a';
		cal(v,st^(1<<c),d+1);
	}
}
void cl(int x,int st){
	mp[xz^st]=0;
	for(int i=head[x];i;i=e[i].next){
		int c=e[i].c-'a';
		cl(e[i].go,st^(1<<c));
	}
}
inline void dfs(int x,int f,int del){  //按顺序调用统计答案函数
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		if(v==f||v==son[x])continue;
		dfs(v,x,1);
	}
	if(son[x])dfs(son[x],x,0),mp[xz]=max(mp[xz],-xl),xz^=(1<<w[x]),xl++;
	//cout<<x<<"  "<<son[x]<<endl;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go,c=e[i].c-'a';
		if(v==son[x]||v==f)continue;
		r=0;cal(v,1<<c,1);
		for(int j=1;j<=r;j++){
			int s=q[j].first,len=q[j].second;
			if(mp[s]>-xl)ans[x]=max(ans[x],mp[s]+len+2*xl);
			for(int k=0;k<23;k++)
				if(mp[s^(1<<k)]>-xl)ans[x]=max(ans[x],mp[s^(1<<k)]+len+2*xl);
		}
		for(int j=1;j<=r;j++)mp[q[j].first]=max(mp[q[j].first],q[j].second);
	}
	ans[x]=max(ans[x],mp[xz]+xl);
	for(int k=0;k<23;k++)ans[x]=max(ans[x],mp[xz^(1<<k)]+xl);
	//debug(x);
	if(del)cl(x,0),xz=0,xl=-N;
}
inline void dfs2(int x){
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].go;
		dfs2(v);
		ans[x]=max(ans[x],ans[v]);
	}
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++){
    	int p;
    	char tc[2];
    	scanf("%d%s",&p,tc);
    	add(p,i,tc[0]);
	}
	get_son(1,0);dfs(1,0,0);dfs2(1);
	for(int i=1;i<=n;i++)printf("%d%c",ans[i],(i==n)?'\n':' ');
	return 0;
}


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

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int N = 500005;
map<int, int> mp;
vector<pair<int, char> > g[N];
int ptr, sz[N], dep[N], vert[N], st[N], en[N], ans[N], mask[N];

void dfs(int v, int p){
	sz[v] = 1;
	dep[v] = dep[p] + 1;
	vert[ptr] = v;
	st[v] = ptr++;
	for(auto x : g[v]){
		if(x.first == p)continue;
		int u = x.first;
		mask[u] = mask[v]^(1<<(x.second - 'a'));
		dfs(u, v);
		sz[v] += sz[u];
	}
	en[v] = ptr;
}

inline int get(int msk){
	int ret = 0;
	if(mp.count(msk))ret = mp[msk];
	for(int i = 0; i < 26; i++){
		if(mp.count(msk^(1<<i)))ret = max(ret, mp[msk^(1<<i)]);
	}
	return ret;
}

void dsu(int v, int p, bool flg){
	int bg = -1;
	for(auto x : g[v]){
		if(x.first != p && (bg == -1 || sz[bg] < sz[x.first]))bg = x.first;
	}
	for(auto x : g[v]){
		if(x.first != p && x.first != bg)dsu(x.first, v, false);
	}
	if(~bg)dsu(bg, v, true);
	mp[mask[v]] = max(mp[mask[v]], dep[v]);
	ans[v] = get(mask[v]) - dep[v];
	for(auto x : g[v]){
		int u = x.first;
		if(u == p || u == bg)continue;
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			ans[v] = max(ans[v], get(mask[w]) + dep[w] - 2*dep[v]);
		}
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			mp[mask[w]] = max(mp[mask[w]], dep[w]);
		}
	}
	if(!flg)mp.clear();
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cout<<setprecision(32);

	int n;
	cin>>n;
	for(int i = 2; i <= n; i++){
		int u; char ch;
		cin>>u>>ch;
		g[u].push_back({i, ch});
	}
	ptr = 1;
	dep[0] = 0;
	mask[0] = mask[1] = 0;
	dfs(1, 0);
	dsu(1, 0, false);
	for(int i = 1; i <= n; i++){
		cout<<ans[i]<<" ";
	}

	return 0;
}


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

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int N = 500005;
int mp[(1<<22)];
vector<pair<int, char> > g[N];
int ptr, sz[N], dep[N], vert[N], st[N], en[N], ans[N], mask[N];

void dfs(int v, int p){
	sz[v] = 1;
	dep[v] = dep[p] + 1;
	vert[ptr] = v;
	st[v] = ptr++;
	for(auto x : g[v]){
		if(x.first == p)continue;
		int u = x.first;
		mask[u] = mask[v]^(1<<(x.second - 'a'));
		dfs(u, v);
		sz[v] += sz[u];
	}
	en[v] = ptr;
}

inline int get(int msk){
	int ret = -1;
	if(~mp[msk])ret = max(ret, mp[msk]);
	for(int i = 0; i < 22; i++){
		if(~mp[msk^(1<<i)])ret = max(ret, mp[msk^(1<<i)]);
	}
	return ret;
}

void dsu(int v, int p, bool flg){
	int bg = -1;
	for(auto x : g[v]){
		if(x.first != p && (bg == -1 || sz[bg] < sz[x.first]))bg = x.first;
	}
	for(auto x : g[v]){
		if(x.first != p && x.first != bg)dsu(x.first, v, false);
	}
	if(~bg)dsu(bg, v, true);
	mp[mask[v]] = max(mp[mask[v]], dep[v]);
	ans[v] = get(mask[v]) - dep[v];
	for(auto x : g[v]){
		int u = x.first;
		if(u == p || u == bg)continue;
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			int tmp = get(mask[w]);
			if(tmp != -1)ans[v] = max(ans[v], tmp + dep[w] - 2*dep[v]);
		}
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			mp[mask[w]] = max(mp[mask[w]], dep[w]);
		}
	}
	if(!flg){
		mp[mask[v]] = -1;
		for(auto x : g[v]){
			int u = x.first;
			if(u == p)continue;
			for(int i = st[u]; i < en[u]; i++){
				int w = vert[i];
				mp[mask[w]] = -1;
			}
		}
	}
}

void ddfs(int v, int p){
	for(auto x : g[v]){
		if(x.first != p){
			ddfs(x.first, v);
			ans[v] = max(ans[v], ans[x.first]);
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cout<<setprecision(32);

	int n;
	cin>>n;
	for(int i = 2; i <= n; i++){
		int u; char ch;
		cin>>u>>ch;
		g[u].push_back({i, ch});
	}
	ptr = 1;
	dep[0] = 0;
	mask[0] = mask[1] = 0;
	dfs(1, 0);
	memset(mp, -1, sizeof(mp));
	dsu(1, 0, false);
	ddfs(1, 0);
	for(int i = 1; i <= n; i++){
		cout<<ans[i]<<" ";
	}

	return 0;
}


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

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int N = 500005;
map<int, int> mp;
vector<pair<int, char> > g[N];
int ptr, sz[N], dep[N], vert[N], st[N], en[N], ans[N], mask[N];

void dfs(int v, int p){
	sz[v] = 1;
	dep[v] = dep[p] + 1;
	vert[ptr] = v;
	st[v] = ptr++;
	for(auto x : g[v]){
		if(x.first == p)continue;
		int u = x.first;
		mask[u] = mask[v]^(1<<(x.second - 'a'));
		dfs(u, v);
		sz[v] += sz[u];
	}
	en[v] = ptr;
}

inline int get(int msk){
	int ret = 0;
	if(mp.count(msk))ret = mp[msk];
	for(int i = 0; i < 26; i++){
		if(mp.count(msk^(1<<i)))ret = max(ret, mp[msk^(1<<i)]);
	}
	return ret;
}

void dsu(int v, int p, bool flg){
	int bg = -1;
	for(auto x : g[v]){
		if(x.first != p && (bg == -1 || sz[bg] < sz[x.first]))bg = x.first;
	}
	for(auto x : g[v]){
		if(x.first != p && x.first != bg)dsu(x.first, v, false);
	}
	if(~bg)dsu(bg, v, true);
	mp[mask[v]] = max(mp[mask[v]], dep[v]);
	ans[v] = get(mask[v]) - dep[v];
	for(auto x : g[v]){
		int u = x.first;
		if(u == p || u == bg)continue;
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			ans[v] = max(ans[v], get(mask[w]) + dep[w] - 2*dep[v]);
		}
		for(int i = st[u]; i < en[u]; i++){
			int w = vert[i];
			mp[mask[w]] = max(mp[mask[w]], dep[w]);
		}
	}
	if(!flg)mp.clear();
}

void ddfs(int v, int p){
	for(auto x : g[v]){
		if(x.first != p)ddfs(x.first, v);
		ans[v] = max(ans[v], ans[x.first]);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cout<<setprecision(32);

	int n;
	cin>>n;
	for(int i = 2; i <= n; i++){
		int u; char ch;
		cin>>u>>ch;
		g[u].push_back({i, ch});
	}
	ptr = 1;
	dep[0] = 0;
	mask[0] = mask[1] = 0;
	dfs(1, 0);
	dsu(1, 0, false);
	ddfs(1, 0);
	for(int i = 1; i <= n; i++){
		cout<<ans[i]<<" ";
	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu_on_tree
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    set<pii> st[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f || v == flag) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu_on_tree ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu_on_tree.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu_on_tree.dfs1(0 , 1 , 0) ;
	dsu_on_tree.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu_on_tree.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
vector<int> g[maxn] ;
struct Dsu_on_tree
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    void init()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   for(int i = 0 ; i < (1 << 22) ; i ++)  cnt[i] = -1e9 ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(auto v : g[u])
	  {
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(auto v : g[u])
      {
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(auto v : g[u])
        {
		   if(v == f || v == flag) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(auto v : g[u])
      {
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(auto v : g[u])
      {
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu_on_tree ;
int main()
{
    //freopen("data.in","r",stdin),freopen("A.out","w",stdout);
    scanf("%d", &n) ;
    dsu_on_tree.init() ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu_on_tree.val[i] = (1 << (s[0] - 'a')) ;
        g[u].push_back(i) ;
        g[i].push_back(u) ;
    }
    dsu_on_tree.dfs1(0 , 1 , 0) ;
	dsu_on_tree.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu_on_tree.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
	void work(int u)
	{
		cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
        ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
        for(int i = 0 ; i < 22 ; i ++)
      	  ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
      }
      if(son[u])  dfs2(u , son[u] , 1) ;
	  work(u) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(keep == -1)  add(f , u , -1) ;
    }
    void update(int f , int u)
    {
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
      	   int v = link.edge[i].v ;
           if(v == f) continue ;
           ans[u] = max(ans[u] , ans[v]) ;
           update(u , v) ;
        }
	}
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
	dsu.update(0 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;//
    return 0 ;//
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	void init()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu_on_tree
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    void init()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   for(int i = 0 ; i < (1 << 22) ; i ++)  cnt[i] = -1e9 ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f || v == flag) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu_on_tree ;
int main()
{
    //freopen("data.in","r",stdin),freopen("A.out","w",stdout);
    scanf("%d", &n) ;
    link.init() ;
    dsu_on_tree.init() ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu_on_tree.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu_on_tree.dfs1(0 , 1 , 0) ;
	dsu_on_tree.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu_on_tree.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])  dfs2(u , son[u] , 1) , ans[u] = max(ans[u] , ans[son[u]]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(keep == -1)  add(f , u , -1) ;
    }
    void update(int f , int u)
    {
         cnt[val[u]] = max(cnt[val[u]] , dep[u]);
         ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
         for(int i = 0 ; i < 22 ; i ++)
      	 ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
      	   int v = link.edge[i].v ;
           if(v == f) continue ;
           ans[u] = max(ans[u] , ans[v]) ;
           update(u , v) ;
        }
	}
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
	dsu.update(0 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu_on_tree
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    void init()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   for(int i = 0 ; i < (1 << 22) ; i ++)  cnt[i] = -1e9 ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f || v == flag) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu_on_tree ;
int main()
{
    //freopen("data.in","r",stdin),freopen("A.out","w",stdout);
    scanf("%d", &n) ;
    dsu_on_tree.init() ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu_on_tree.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu_on_tree.dfs1(0 , 1 , 0) ;
	dsu_on_tree.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu_on_tree.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])  dfs2(u , son[u] , 1) , ans[u] = max(ans[u] , ans[son[u]]) ;
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(keep == -1)  add(f , u , -1) ;
    }
    void update(int f , int u)
    {
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
      	   int v = link.edge[i].v ;
           if(v == f) continue ;
           ans[u] = max(ans[u] , ans[v]) ;
           update(u , v) ;
        }
	}
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
	dsu.update(0 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    set<pii> st[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    set<pii> st[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    int flag ;
    set<pii> st[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   flag = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == flag) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
         ans[u] = max(ans[u] , ans[v]) ;
      }
      if(son[u])
	  {
	     dfs2(u , son[u] , 1) , flag = son[u] ;
		 ans[u] = max(ans[u] , ans[son[u]]) ;
	  }
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         if(v != son[u])
         {
            cal(u , u , v) ;
            add(u , v , 1) ;
         }
      }
      if(son[u])  flag = 0 ;
      if(keep == -1)  add(f , u , -1) ;
    }
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%lld " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 5e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , c[maxn] ;
struct Link
{
	int num , head[maxn] ;
	struct Edge
	{
		int v , next ;
	} edge[maxn << 1] ;
	Link()
	{
		num = 0 ;
		memset(head , -1 , sizeof(head)) ;
	}
	void add_edge(int u , int v)
	{
		edge[num].v = v ;
		edge[num].next = head[u] ;
		head[u] = num ++ ;
	}
} link ;
struct Dsu
{
	int siz[maxn] , son[maxn] , dep[maxn] ;
    int val[maxn] , cnt[maxm] , ans[maxn] ;
    Dsu()
	{
	   val[1] = 0 ;
	   memset(siz , 0 , sizeof(siz)) ;
	   memset(son , 0 , sizeof(son)) ;
	   memset(ans , 0 , sizeof(ans)) ;
	   memset(cnt , 0 , sizeof(cnt)) ;
	}
	void dfs1(int f , int u , int s)
    {
      siz[u] = 1 ;
	  dep[u] = s ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
	  {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         val[v] ^= val[u] ;
         dfs1(u , v , s + 1) ;
		 siz[u] += siz[v] ;
         if(siz[v] > siz[son[u]]) son[u] = v ;
      }
    }
    void add(int f , int u , int keep)
    {
      if(keep == 1)  cnt[val[u]] = max(cnt[val[u]] , dep[u]) ;
      else  cnt[val[u]] = -1e9 ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f) continue ;
         add(u , v , keep) ;
      }
    }
    void cal(int x , int f , int u)
    {
    	ans[x] = max(ans[x] , cnt[val[u]] + dep[u] - 2 * dep[x]) ;
        for(int i = 0 ; i < 22 ; i ++)
          ans[x] = max(ans[x] , cnt[val[u] ^ (1 << i)] + dep[u] - 2 * dep[x]) ;
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
		   int v = link.edge[i].v ;
		   if(v == f) continue ;
		   cal(x , u , v) ;
	    }
	}
    void dfs2(int f , int u , int keep)
    {
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
		 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         dfs2(u , v , -1) ;
      }
      if(son[u])  dfs2(u , son[u] , 1) ;
	  cnt[val[u]] = max(cnt[val[u]] , dep[u]);
      ans[u] = max(ans[u] , cnt[val[u]] - dep[u]) ;
      for(int i = 0 ; i < 22 ; i ++)
      	ans[u] = max(ans[u] , cnt[val[u] ^ (1 << i)] - dep[u]) ;
      for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
      {
      	 int v = link.edge[i].v ;
         if(v == f || v == son[u]) continue ;
         cal(u , u , v) ;
         add(u , v , 1) ;
      }
      if(keep == -1)  add(f , u , -1) ;
    }
    void update(int f , int u)
    {
    	for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next)
        {
      	   int v = link.edge[i].v ;
           if(v == f) continue ;
           ans[u] = max(ans[u] , ans[v]) ;
           update(u , v) ;
        }
	}
} dsu ;
int main()
{
    scanf("%d", &n) ;
    for(int i = 2 ; i <= n ; i ++)
	{
        int u ;
		char s[5] ;
        scanf("%d%s" , &u , s) ;
        dsu.val[i] = (1 << (s[0] - 'a')) ;
        link.add_edge(u , i) ;
	    link.add_edge(i , u) ;
    }
    dsu.dfs1(0 , 1 , 0) ;
	dsu.dfs2(0 , 1 , 1) ;
	dsu.update(0 , 1) ;
    for(int i = 1 ; i <= n ; i ++)  printf("%d " , dsu.ans[i]) ;
    printf("\n") ;
    return 0 ;
}


#include<bits/stdc++.h>
#define Cell pair<int,int>
using namespace std;
typedef long long ll;

const int maxn = 5e5 + 10;
const int inf = 1e5 + 10;

int a[maxn];
vector<int> t[maxn];
int dp[(1 << 22) + 10];
int h[maxn], sz[maxn];
int Time = 1, st[maxn], ft[maxn], pos[maxn];
int answer = 0;
int ans[maxn];

void add(int x, int H){
	dp[x] = H;
}

int ask(int x, int H){
	int ret = dp[x] + H;
	for (int i = 0; i < 22; i++){
		x ^= (1 << i);
		ret = max(ret, dp[x] + H);
		x ^= (1 << i);
	}
	return ret;
}

void dfs(int v, bool heavy = 0){
	if (t[v].empty()){
		if (heavy == 1)
			add(a[v], h[v]);
		return;
	}
	int bc = t[v].back();
	for (auto u : t[v]){
		dfs(u, (u == bc));
		ans[v] = max(ans[v], ans[u]);
	}
	int last = st[v];
	for (int i = st[v]; i < st[bc]; i++){
		int u = pos[i];
		if (ft[last] <= st[u]){
			while (last < i){
				int w = pos[last];
				add(a[w], h[w]);
				last ++;
			}
		}
		ans[v] = max(ans[v], ask(a[u], h[u] - 2 * h[v]));
	}
	if (heavy == 0)
		for (int i = st[v]; i < ft[v]; i++)
			add(a[pos[i]], -inf);
}

int cmp(int v, int u){
	return sz[v] < sz[u];
}

void dfs_st(int v){
	pos[Time] = v;
	st[v] = Time ++;
	for (auto u : t[v]){
		h[u] = h[v] + 1;
		dfs_st(u);
	}
	ft[v] = Time;
}

int dfs_sz(int v){
	sz[v] = 1;
	for (auto u : t[v])
		sz[v] += dfs_sz(u);
	sort(t[v].begin(), t[v].end());
	return sz[v];
}

int main(){
	ios_base::sync_with_stdio(false);
	memset(dp, -63, sizeof dp);
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++){
		int p;
		char c;
		cin >> p >> c;
		int x = (int)(c - 'a');
		a[i] = (a[p] ^ (1 << x));
		t[p].push_back(i);
	}
	dfs_sz(1);
	dfs_st(1);
	dfs(1);
	for (int i = 1; i <= n; i++)
		cout << ans[i] << " \n"[i == n];
}


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

const int maxn = 5e5 + 10;
const int inf = 1e5 + 10;

int a[maxn];
vector<int> t[maxn];
int dp[(1 << 22) + 10];
int h[maxn], sz[maxn];
int Time = 1, st[maxn], ft[maxn], pos[maxn];
int answer = 0;
int ans[maxn];

void add(int x, int H){
	if (H < 0)
		dp[x] = H;
	else
		dp[x] = max(dp[x], H);
}

int ask(int x, int H){
	int ret = dp[x] + H;
	for (int i = 0; i < 22; i++){
		x ^= (1 << i);
		ret = max(ret, dp[x] + H);
		x ^= (1 << i);
	}
	return ret;
}

void dfs(int v, bool heavy = 0){
	if (t[v].empty()){
		if (heavy == 1)
			add(a[v], h[v]);
		return;
	}
	int bc = t[v].back();
	for (auto u : t[v]){
		dfs(u, (u == bc));
		ans[v] = max(ans[v], ans[u]);
	}
	int last = st[v] + 1;
	ans[v] = max(ans[v], ask(a[v], -h[v]));
	add(a[v], h[v]);
	for (int i = st[v] + 1; i <= st[bc]; i++){
		int u = pos[i];
		if (ft[pos[last]] <= st[u]){
			while (last < i){
				int w = pos[last];
				add(a[w], h[w]);
				last ++;
			}
		}
		if (i == st[bc])
			break;
		ans[v] = max(ans[v], ask(a[u], h[u] - 2 * h[v]));
	}
	if (heavy == 0)
		for (int i = st[v]; i < ft[v]; i++){
			add(a[pos[i]], -inf);
		}
}

int cmp(int v, int u){
	return sz[v] < sz[u];
}

void dfs_st(int v){
	pos[Time] = v;
	st[v] = Time ++;
	for (auto u : t[v]){
		h[u] = h[v] + 1;
		dfs_st(u);
	}
	ft[v] = Time;
}

int dfs_sz(int v){
	sz[v] = 1;
	for (auto u : t[v])
		sz[v] += dfs_sz(u);
	sort(t[v].begin(), t[v].end(), cmp);
	return sz[v];
}

int main(){
	ios_base::sync_with_stdio(false);
	memset(dp, -63, sizeof dp);
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++){
		int p;
		char c;
		cin >> p >> c;
		int x = (int)(c - 'a');
		a[i] = (a[p] ^ (1 << x));
		t[p].push_back(i);
	}
	dfs_sz(1);
	dfs_st(1);
	dfs(1);
	for (int i = 1; i <= n; i++)
		cout << ans[i] << " \n"[i == n];
}


#include<bits/stdc++.h>
#define Cell pair<int,int>
using namespace std;
typedef long long ll;

const int maxn = 5e5 + 10;

int a[maxn];
vector<int> t[maxn];
int dp[(1 << 22) + 10];
int h[maxn], sz[maxn];
int Time = 1, st[maxn], ft[maxn], pos[maxn];
int answer = 0;
int ans[maxn];

void add(int x, int H){
	dp[x] = H;
}

int ask(int x, int H){
	int ret = dp[x] + H;
	for (int i = 0; i < 22; i++){
		x ^= (1 << i);
		ret = max(ret, dp[x] + H);
		x ^= (1 << i);
	}
	return ret;
}

void dfs(int v, bool heavy = 0){
	if (t[v].empty()){
		if (heavy == 1)
			add(a[v], h[v]);
		return;
	}
	int bc = t[v].back();
	for (auto u : t[v]){
		dfs(u, (u == bc));
		ans[v] = max(ans[v], ans[u]);
	}
	int last = st[v];
	for (int i = st[v]; i < st[bc]; i++){
		int u = pos[i];
		if (ft[last] <= st[u]){
			while (last < i){
				int w = pos[last];
				add(a[w], h[w]);
				last ++;
			}
		}
		ans[v] = max(ans[v], ask(a[u], h[u] - 2 * h[v]));
	}
	if (heavy == 0)
		for (int i = st[v]; i < ft[v]; i++)
			add(a[pos[i]], 0);
}

int cmp(int v, int u){
	return sz[v] < sz[u];
}

void dfs_st(int v){
	pos[Time] = v;
	st[v] = Time ++;
	for (auto u : t[v]){
		h[u] = h[v] + 1;
		dfs_st(u);
	}
	ft[v] = Time;
}

int dfs_sz(int v){
	sz[v] = 1;
	for (auto u : t[v])
		sz[v] += dfs_sz(u);
	sort(t[v].begin(), t[v].end());
	return sz[v];
}

int main(){
	ios_base::sync_with_stdio(false);
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++){
		int p;
		char c;
		cin >> p >> c;
		int x = (int)(c - 'a');
		a[i] = (a[p] ^ (1 << x));
		t[p].push_back(i);
	}
	dfs_sz(1);
	dfs_st(1);
	dfs(1);
	for (int i = 1; i <= n; i++)
		cout << ans[i] << " \n"[i == n];
}


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

const int maxn = 5e5 + 10;
const int inf = 1e5 + 10;

int a[maxn];
vector<int> t[maxn];
int dp[(1 << 22) + 10];
int h[maxn], sz[maxn];
int Time = 1, st[maxn], ft[maxn], pos[maxn];
int answer = 0;
int ans[maxn];

void add(int x, int H){
	dp[x] = H;
}

int ask(int x, int H){
	int ret = dp[x] + H;
	for (int i = 0; i < 22; i++){
		x ^= (1 << i);
		ret = max(ret, dp[x] + H);
		x ^= (1 << i);
	}
	return ret;
}

void dfs(int v, bool heavy = 0){
	if (t[v].empty()){
		if (heavy == 1)
			add(a[v], h[v]);
		return;
	}
	int bc = t[v].back();
	for (auto u : t[v]){
		dfs(u, (u == bc));
		ans[v] = max(ans[v], ans[u]);
	}
	int last = st[v] + 1;
	ans[v] = max(ans[v], ask(a[v], -h[v]));
	add(a[v], h[v]);
	for (int i = st[v]; i <= st[bc]; i++){
		int u = pos[i];
		if (ft[pos[last]] <= st[u]){
			while (last < i){
				int w = pos[last];
				add(a[w], h[w]);
				last ++;
			}
		}
		if (i == st[bc])
			break;
		ans[v] = max(ans[v], ask(a[u], h[u] - 2 * h[v]));
	}
	if (heavy == 0)
		for (int i = st[v]; i < ft[v]; i++){
			add(a[pos[i]], -inf);
		}
}

int cmp(int v, int u){
	return sz[v] < sz[u];
}

void dfs_st(int v){
	pos[Time] = v;
	st[v] = Time ++;
	for (auto u : t[v]){
		h[u] = h[v] + 1;
		dfs_st(u);
	}
	ft[v] = Time;
}

int dfs_sz(int v){
	sz[v] = 1;
	for (auto u : t[v])
		sz[v] += dfs_sz(u);
	sort(t[v].begin(), t[v].end(), cmp);
	return sz[v];
}

int main(){
	ios_base::sync_with_stdio(false);
	memset(dp, -63, sizeof dp);
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++){
		int p;
		char c;
		cin >> p >> c;
		int x = (int)(c - 'a');
		a[i] = (a[p] ^ (1 << x));
		t[p].push_back(i);
	}
	dfs_sz(1);
	dfs_st(1);
	dfs(1);
	for (int i = 1; i <= n; i++)
		cout << ans[i] << " \n"[i == n];
}


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

const int maxn = 5e5 + 10;
const int inf = 1e5 + 10;

int a[maxn];
vector<int> t[maxn];
int dp[(1 << 22) + 10];
int h[maxn], sz[maxn];
int Time = 1, st[maxn], ft[maxn], pos[maxn];
int answer = 0;
int ans[maxn];

void add(int x, int H){
	dp[x] = H;
}

int ask(int x, int H){
	int ret = dp[x] + H;
	for (int i = 0; i < 22; i++){
		x ^= (1 << i);
		ret = max(ret, dp[x] + H);
		x ^= (1 << i);
	}
	return ret;
}

void dfs(int v, bool heavy = 0){
//	cout << "DFS " << v << " " << heavy << endl;
	if (t[v].empty()){
		if (heavy == 1){
//			cout << "Add : " << v << " : " << a[v] << endl;
			add(a[v], h[v]);
		}
		return;
	}
	int bc = t[v].back();
	for (auto u : t[v]){
		dfs(u, (u == bc));
		ans[v] = max(ans[v], ans[u]);
	}
	int last = st[v];
	for (int i = st[v]; i <= st[bc]; i++){
		int u = pos[i];
		if (ft[last] <= st[u]){
			while (last < i){
				int w = pos[last];
//				cout << "Add : " << w << " : " << a[w] << endl;
				add(a[w], h[w]);
				last ++;
			}
		}
		if (i == st[bc])
			break;
		ans[v] = max(ans[v], ask(a[u], h[u] - 2 * h[v]));
//		cout << "Get : " << v << " : " << u << " -> " << ask(a[u], h[u] - 2 * h[v]) << endl;
	}
	if (heavy == 0)
		for (int i = st[v]; i < ft[v]; i++){
//			cout << "Add : " << pos[i] << " " << -inf << endl;
			add(a[pos[i]], -inf);
		}
}

int cmp(int v, int u){
	return sz[v] < sz[u];
}

void dfs_st(int v){
	pos[Time] = v;
	st[v] = Time ++;
	for (auto u : t[v]){
		h[u] = h[v] + 1;
		dfs_st(u);
	}
	ft[v] = Time;
}

int dfs_sz(int v){
	sz[v] = 1;
	for (auto u : t[v])
		sz[v] += dfs_sz(u);
	sort(t[v].begin(), t[v].end(), cmp);
	return sz[v];
}

int main(){
	ios_base::sync_with_stdio(false);
	memset(dp, -63, sizeof dp);
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++){
		int p;
		char c;
		cin >> p >> c;
		int x = (int)(c - 'a');
		a[i] = (a[p] ^ (1 << x));
		t[p].push_back(i);
	}
	dfs_sz(1);
	dfs_st(1);
	dfs(1);
	for (int i = 1; i <= n; i++)
		cout << ans[i] << " \n"[i == n];
}


#include<bits/stdc++.h>
using namespace std;
const int N=500009;
const int INF=1e9;
int n,m,L,bst,son[N],p[N],sz[N],d[N],ans[N],cnt[N],path[N],mx[1<<22];
int timer,tI[N],tO[N],id[N];
struct edge{int v,c;} e[N*2];
int hd[N*2],nxt[N*2],nE;
struct query{int id,k;};
vector<query> q[N];
void addedge(int u,int v,int c){
	e[++nE]=(edge){v,c},nxt[nE]=hd[u],hd[u]=nE;
}
void dfs_pre(int u){
	d[u]=d[p[u]]+1;
	sz[u]=1;
	son[u]=0;
	id[tI[u]=++timer]=u;
	for(int i=hd[u];i;i=nxt[i]){
		int v=e[i].v;
		path[v]=path[u]^(1<<e[i].c);
        dfs_pre(v);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v])son[u]=v;
    }
    tO[u]=timer;
}
void upd(int&res,int x){if(x>res)res=x;}
void useNode(int u,int lca){
	upd(bst,mx[path[u]]+d[u]-d[lca]*2);
	for(int i=0;i<22;++i)
		upd(bst,mx[path[u]^(1<<i)]+d[u]-d[lca]*2);
}
void useTree(int u,int lca){
	for(int i=tI[u];i<=tO[u];++i)useNode(id[i],lca);
}
void addNode(int u,bool ADD){
	if(ADD)	upd(mx[path[u]],d[u]);
	else mx[path[u]]=-INF;
}
void addTree(int u,bool ADD){
	for(int i=tI[u];i<=tO[u];++i)addNode(id[i],ADD);
}
void dfs(int u,bool hvy){
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)dfs(e[i].v,0),upd(ans[u],ans[e[i].v]);
	if(son[u])dfs(son[u],1),upd(ans[u],ans[son[u]]);
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)useTree(e[i].v,u),addTree(e[i].v,1);
	useNode(u,u), addNode(u,1);
	upd(ans[u],bst);
	if(hvy)return;
	addTree(u,0);
	bst=-INF;
}
void solve(){
	scanf("%d",&n);
	for(int u=2;u<=n;++u){
		scanf("%d ",&p[u]);
		char ch;
		scanf("%c",&ch);
		if(p[u])addedge(p[u],u,ch-'a');
	}
	dfs_pre(1);
	dfs(1,0);
	for(int u=1;u<n;++u)printf("%d ",ans[u]);
	printf("%d\n",ans[n]);
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	solve();
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=500009;
const int INF=1e9;
int n,m,L,bst,son[N],p[N],sz[N],d[N],ans[N],cnt[N],path[N],mx[1<<22];
int timer,tI[N],tO[N],id[N];
struct edge{int v,c;} e[N*2];
int hd[N*2],nxt[N*2],nE;
struct query{int id,k;};
vector<query> q[N];
void addedge(int u,int v,int c){
	e[++nE]=(edge){v,c},nxt[nE]=hd[u],hd[u]=nE;
}
void dfs_pre(int u){
	d[u]=d[p[u]]+1;
	sz[u]=1;
	son[u]=0;
	id[tI[u]=++timer]=u;
	for(int i=hd[u];i;i=nxt[i]){
		int v=e[i].v;
		path[v]=path[u]^(1<<e[i].c);
        dfs_pre(v);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v])son[u]=v;
    }
    tO[u]=timer;
}
void upd(int&res,int x){if(x>res)res=x;}
void useNode(int u,int lca){
	upd(bst,mx[path[u]]+d[u]-d[lca]*2);
	for(int i=0;i<22;++i)
		upd(bst,mx[path[u]^(1<<i)]+d[u]-d[lca]*2);
}
void useTree(int u,int lca){
	for(int i=tI[u];i<=tO[u];++i)useNode(id[i],lca);
}
void addNode(int u,bool ADD){
	if(ADD)	upd(mx[path[u]],d[u]);
	else mx[path[u]]=-INF;
}
void addTree(int u,bool ADD){
	for(int i=tI[u];i<=tO[u];++i)addNode(id[i],ADD);
}
void dfs(int u,bool hvy){
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)dfs(e[i].v,0),upd(ans[u],ans[e[i].v]);
	if(son[u])dfs(son[u],1),upd(ans[u],ans[son[u]]);
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)useTree(e[i].v,u),addTree(e[i].v,1);
	useNode(u,u), addNode(u,1);
	upd(ans[u],bst);
	if(hvy)return;
	addTree(u,0);
	bst=0;
}
void input(){
	scanf("%d",&n);
	fill(mx,mx+(1<<22),-INF);
	for(int u=2;u<=n;++u){
		scanf("%d ",&p[u]);
		char ch;
		scanf("%c",&ch);
		addedge(p[u],u,ch-'a');
	}
}
void solve(){
	dfs_pre(1);
	dfs(1,0);
	for(int u=1;u<n;++u)printf("%d ",ans[u]);
	printf("%d\n",ans[n]);
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	input();
	solve();
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=500009;
const int INF=1e9;
int n,m,L,bst,son[N],p[N],sz[N],d[N],ans[N],cnt[N],path[N],mx[1<<22];
int timer,tI[N],tO[N],id[N];
struct edge{int v,c;} e[N*2];
int hd[N*2],nxt[N*2],nE;
struct query{int id,k;};
vector<query> q[N];
void addedge(int u,int v,int c){
	e[++nE]=(edge){v,c},nxt[nE]=hd[u],hd[u]=nE;
}
void dfs_pre(int u){
	d[u]=d[p[u]]+1;
	sz[u]=1;
	son[u]=0;
	id[tI[u]=++timer]=u;
	for(int i=hd[u];i;i=nxt[i]){
		int v=e[i].v;
		path[v]=path[u]^(1<<e[i].c);
        dfs_pre(v);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v])son[u]=v;
    }
    tO[u]=timer;
}
void upd(int&res,int x){if(x>res)res=x;}
void useNode(int u,int lca){
	upd(bst,mx[path[u]]+d[u]-d[lca]*2);
	for(int i=0;i<22;++i)
		upd(bst,mx[path[u]^(1<<i)]+d[u]-d[lca]*2);
}
void useTree(int u,int lca){
	for(int i=tI[u];i<=tO[u];++i)useNode(id[i],lca);
}
void addNode(int u,bool ADD){
	if(ADD)	upd(mx[path[u]],d[u]);
	else mx[path[u]]=-INF;
}
void addTree(int u,bool ADD){
	for(int i=tI[u];i<=tO[u];++i)addNode(id[i],ADD);
}
void dfs(int u,bool hvy){
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)dfs(e[i].v,0),upd(ans[u],ans[e[i].v]);
	if(son[u])dfs(son[u],1),upd(ans[u],ans[son[u]]);
	for(int i=hd[u];i;i=nxt[i])
		if(son[u]!=e[i].v)useTree(e[i].v,u),addTree(e[i].v,1);
	useNode(u,u), addNode(u,1);
	upd(ans[u],bst);
	if(hvy)return;
	addTree(u,0);
	bst=0;
}
void input(){
	scanf("%d",&n);
	for(int u=2;u<=n;++u){
		scanf("%d ",&p[u]);
		char ch;
		scanf("%c",&ch);
		addedge(p[u],u,ch-'a');
	}
}
void solve(){
	dfs_pre(1);
	dfs(1,0);
	for(int u=1;u<n;++u)printf("%d ",ans[u]);
	printf("%d\n",ans[n]);
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	input();
	solve();
    return 0;
}


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

typedef int ll ;
typedef long double ld ;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define plch pair<ll,char>

const ll maxn = 5e5 + 10 ;
const ll maxn2 = (1<<22)+3 ;
const ll INF = 1e18 ;

ll n , sub[maxn] , h[maxn] , va[maxn]  , maxh[maxn2] , ans[maxn] ;
vector<plch> g[maxn] ;
vector<ll> vec[maxn] ;

void dfs(ll v , ll p , ll now)
{
 va[v] = now ;
 sub[v] = 1;
 for(auto uu : g[v]){
    if(uu.f != p){
      h[uu.f] = h[v]+1;
      dfs(uu.f , v , now^(1<<(uu.s-'a'))) ;
      sub[v] += sub[uu.f] ;
    }
 }
}

ll up(ll x)
{
  ll anss = maxh[x] ;
  for(int i = 0 ;i < 22 ; i ++)
   anss = max(anss , maxh[x^(1<<i)]) ;
  return anss ;
}

void gooni(ll v , ll p , bool keep)
{
 ll mx = -1 , bigch = -1 ;

 for(auto uu : g[v])
   if(uu.f != p)
    if(sub[uu.f] > mx)
       mx = sub[uu.f] , bigch = uu.f ;

 for(auto uu : g[v])
  if(uu.f != p && uu.f != bigch)
    gooni(uu.f , v , 0) ;

 if(bigch != -1){
    gooni(bigch , v , 1) ;
    swap(vec[v] , vec[bigch]) ;
 }

  for(auto uu : g[v]){
    if(uu.f != p && uu.f != bigch){
     for(auto x : vec[uu.f]){

      if(__builtin_popcount(va[x]^va[v]) < 2)
       ans[v] = max(ans[v] , h[x]-h[v]) ;

      ll maxx = up(va[x]) ;
      if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
      vec[v].pb(x);
     }
     for(auto x : vec[uu.f])
        maxh[va[x]] = max(maxh[va[x]] , h[x]) ;
    }
  }

   vec[v].pb(v);
   ll maxx = up(va[v]) ;
   if(maxx != 0)ans[v] = max(ans[v] , maxx+h[v]-(2*h[v])) ;
   maxh[va[v]] = max(maxh[va[v]] , h[v]) ;

  for(auto uu : g[v])
    if(uu.f != p)
     ans[v] = max(ans[v] , ans[uu.f]) ;

  if(keep == 0){
    for(auto x : vec[v])
      maxh[va[x]] = 0;
  }
}

int main()
{
// std::ios::sync_with_stdio(0) ;
// cin.tie(0) ;
// cout.tie(0);

 scanf("%d" , &n) ;
 for(int i = 2 ; i <= n ; i ++){
    ll v ;
    char ch ;
    scanf("%d %c" , &v , &ch) ;
    g[v].pb({i , ch}) ;
    g[i].pb({v , ch}) ;
 }
 h[1] = 1 ;
 dfs(1 , 0 , 0) ;

 gooni(1 , 0 , 1) ;

 for(int i = 1 ;i <= n ; i ++)printf("%d " , ans[i]) ;

    return 0;
}


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

typedef int ll ;
typedef long double ld ;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define plch pair<ll,char>

const ll maxn = 5e5 + 10 ;
const ll maxn2 = (1<<22)+3 ;
const ll INF = 1e18 ;

ll n , sub[maxn] , h[maxn] , va[maxn]  , maxh[maxn2] , ans[maxn] ;
vector<plch> g[maxn] ;
vector<ll> vec[maxn] ;

void dfs(ll v , ll p , ll now)
{
 va[v] = now ;
 sub[v] = 1;
 for(auto uu : g[v]){
    if(uu.f != p){
      h[uu.f] = h[v]+1;
      dfs(uu.f , v , now^(1<<(uu.s-'a'))) ;
      sub[v] += sub[uu.f] ;
    }
 }
}

ll up(ll x)
{
  ll anss = maxh[x] ;
  for(int i = 0 ;i < 22 ; i ++)
   anss = max(anss , maxh[x^(1<<i)]) ;
  return anss ;
}

void gooni(ll v , ll p , bool keep)
{
 ll mx = -1 , bigch = -1 ;
 vector<ll> smalls ;
 map<ll,ll> per , suf;

 for(auto uu : g[v])
   if(uu.f != p)
    if(sub[uu.f] > mx)
       mx = sub[uu.f] , bigch = uu.f ;

 for(auto uu : g[v])
  if(uu.f != p && uu.f != bigch)
    gooni(uu.f , v , 0) ;

 if(bigch != -1){
    gooni(bigch , v , 1) ;
    swap(vec[v] , vec[bigch]) ;
 }

  for(auto uu : g[v])
    if(uu.f != p && uu.f != bigch)
     for(auto x : vec[uu.f])
      smalls.pb(x);

  for(auto x : smalls)
    if(__builtin_popcount(va[x]^va[v]) < 2)
       ans[v] = max(ans[v] , h[x]-h[v]) ;

  smalls.pb(v) ;

  for(auto x : smalls){
   ll maxx = up(va[x]) ;
   if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
  }

  for(int i = 0 ; i < g[v].size() ; i ++){
    if(g[v][i].f != p && g[v][i].f != bigch){
       ll u = g[v][i].f ;
       for(auto x : vec[u]){
          ll maxx = per[va[x]] ;
          for(int i = 0 ;i < 22 ; i ++)
            maxx = max(maxx , per[va[x]^(1<<i)]) ;

         if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
       }
       for(auto x : vec[u])
         per[va[x]] = max(per[va[x]] , h[x]) ;
    }
  }
  for(int i = g[v].size()-1 ; i >= 0 ; i --){
    if(g[v][i].f != p && g[v][i].f != bigch){
       ll u = g[v][i].f ;
       for(auto x : vec[u]){
         ll maxx = suf[va[x]] ;
          for(int i = 0 ;i < 22 ; i ++)
            maxx = max(maxx , suf[va[x]^(1<<i)]) ;

         if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
       }
       for(auto x : vec[u])
         suf[va[x]] = max(suf[va[x]] , h[x]) ;
    }
  }

  for(auto uu : g[v])
    if(uu.f != p)
     ans[v] = max(ans[v] , ans[uu.f]) ;

  for(auto x : smalls){
    vec[v].pb(x) ;
    maxh[va[x]] = max(maxh[va[x]] , h[x]) ;
  }

  if(keep == 0){
    for(auto x : vec[v])
      maxh[va[x]] = 0;
  }
}

int main()
{
 std::ios::sync_with_stdio(0) ;
 cin.tie(0) ;
 cout.tie(0);

 cin >> n ;
 for(int i = 2 ; i <= n ; i ++){
    ll v ;
    char ch ;
    cin >> v >> ch ;
    g[v].pb({i , ch}) ;
    g[i].pb({v , ch}) ;
 }
 h[1] = 1 ;
 dfs(1 , 0 , 0) ;

 gooni(1 , 0 , 1) ;

 for(int i = 1 ;i <= n ; i ++)cout << ans[i] << " " ;

    return 0;
}


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

typedef int ll ;
typedef long double ld ;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define plch pair<ll,char>

const ll maxn = 5e5 + 10 ;
const ll maxn2 = (1<<22)+3 ;
const ll INF = 1e18 ;

ll n , sub[maxn] , h[maxn] , va[maxn]  , maxh[maxn2] , ans[maxn] ;
vector<plch> g[maxn] ;
vector<ll> vec[maxn] ;

void dfs(ll v , ll p , ll now)
{
 va[v] = now ;
 sub[v] = 1;
 for(auto uu : g[v]){
    if(uu.f != p){
      h[uu.f] = h[v]+1;
      dfs(uu.f , v , now^(1<<(uu.s-'a'))) ;
      sub[v] += sub[uu.f] ;
    }
 }
}

ll up(ll x)
{
  ll anss = maxh[x] ;
  for(int i = 0 ;i < 22 ; i ++)
   anss = max(anss , maxh[x^(1<<i)]) ;
  return anss ;
}

void gooni(ll v , ll p , bool keep)
{
 ll mx = -1 , bigch = -1 ;
 vector<ll> smalls ;
 map<ll,ll> per ;

 for(auto uu : g[v])
   if(uu.f != p)
    if(sub[uu.f] > mx)
       mx = sub[uu.f] , bigch = uu.f ;

 for(auto uu : g[v])
  if(uu.f != p && uu.f != bigch)
    gooni(uu.f , v , 0) ;

 if(bigch != -1){
    gooni(bigch , v , 1) ;
    swap(vec[v] , vec[bigch]) ;
 }

  for(auto uu : g[v])
    if(uu.f != p && uu.f != bigch)
     for(auto x : vec[uu.f])
      smalls.pb(x);

  for(auto x : smalls)
    if(__builtin_popcount(va[x]^va[v]) < 2)
       ans[v] = max(ans[v] , h[x]-h[v]) ;

  smalls.pb(v) ;

  for(auto x : smalls){
   ll maxx = up(va[x]) ;
   if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
  }

  for(int i = 0 ; i < g[v].size() ; i ++){
    if(g[v][i].f != p && g[v][i].f != bigch){
       ll u = g[v][i].f ;
       for(auto x : vec[u]){
          ll maxx = per[va[x]] ;
          for(int i = 0 ;i < 22 ; i ++)
            maxx = max(maxx , per[va[x]^(1<<i)]) ;

         if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
       }
       for(auto x : vec[u])
         per[va[x]] = max(per[va[x]] , h[x]) ;
    }
  }

  for(auto uu : g[v])
    if(uu.f != p)
     ans[v] = max(ans[v] , ans[uu.f]) ;

  for(auto x : smalls){
    vec[v].pb(x) ;
    maxh[va[x]] = max(maxh[va[x]] , h[x]) ;
  }

  if(keep == 0){
    for(auto x : vec[v])
      maxh[va[x]] = 0;
  }
}

int main()
{
 std::ios::sync_with_stdio(0) ;
 cin.tie(0) ;
 cout.tie(0);

 cin >> n ;
 for(int i = 2 ; i <= n ; i ++){
    ll v ;
    char ch ;
    cin >> v >> ch ;
    g[v].pb({i , ch}) ;
    g[i].pb({v , ch}) ;
 }
 h[1] = 1 ;
 dfs(1 , 0 , 0) ;

 gooni(1 , 0 , 1) ;

 for(int i = 1 ;i <= n ; i ++)cout << ans[i] << " " ;

    return 0;
}


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

typedef long long ll ;
typedef long double ld ;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define plch pair<ll,char>

const ll maxn = 5e5 + 10 ;
const ll maxn2 = (1<<22)+3 ;
const ll INF = 1e18 ;

ll n , sub[maxn] , h[maxn] , va[maxn]  , maxh[maxn2] , ans[maxn] ;
vector<plch> g[maxn] ;
vector<ll> vec[maxn] ;

void dfs(ll v , ll p , ll now)
{
 va[v] = now ;
 sub[v] = 1;
 for(auto uu : g[v]){
    if(uu.f != p){
      h[uu.f] = h[v]+1;
      dfs(uu.f , v , now^(1<<(uu.s-'a'))) ;
      sub[v] += sub[uu.f] ;
    }
 }
}

ll up(ll x)
{
  ll anss = maxh[x] ;
  for(int i = 0 ;i < 22 ; i ++)
   anss = max(anss , maxh[x^(1<<i)]) ;
  return anss ;
}

void gooni(ll v , ll p , bool keep)
{
 ll mx = -1 , bigch = -1 ;
 vector<ll> smalls ;
 map<ll,ll> per , suf;

 for(auto uu : g[v])
   if(uu.f != p)
    if(sub[uu.f] > mx)
       mx = sub[uu.f] , bigch = uu.f ;

 for(auto uu : g[v])
  if(uu.f != p && uu.f != bigch)
    gooni(uu.f , v , 0) ;

 if(bigch != -1){
    gooni(bigch , v , 1) ;
    swap(vec[v] , vec[bigch]) ;
 }

  for(auto uu : g[v])
    if(uu.f != p && uu.f != bigch)
     for(auto x : vec[uu.f])
      smalls.pb(x);

  for(auto x : smalls)
    if(__builtin_popcount(va[x]^va[v]) < 2)
       ans[v] = max(ans[v] , h[x]-h[v]) ;

  smalls.pb(v) ;

  for(auto x : smalls){
   ll maxx = up(va[x]) ;
   if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
  }

  for(int i = 0 ; i < g[v].size() ; i ++){
    if(g[v][i].f != p && g[v][i].f != bigch){
       ll u = g[v][i].f ;
       for(auto x : vec[u]){
          ll maxx = per[va[x]] ;
          for(int i = 0 ;i < 22 ; i ++)
            maxx = max(maxx , per[va[x]^(1<<i)]) ;

         if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
       }
       for(auto x : vec[u])
         per[va[x]] = max(per[va[x]] , h[x]) ;
    }
  }
  for(int i = g[v].size()-1 ; i >= 0 ; i --){
    if(g[v][i].f != p && g[v][i].f != bigch){
       ll u = g[v][i].f ;
       for(auto x : vec[u]){
         ll maxx = suf[va[x]] ;
          for(int i = 0 ;i < 22 ; i ++)
            maxx = max(maxx , suf[va[x]^(1<<i)]) ;

         if(maxx != 0)ans[v] = max(ans[v] , maxx+h[x]-(2*h[v])) ;
       }
       for(auto x : vec[u])
         suf[va[x]] = max(suf[va[x]] , h[x]) ;
    }
  }

  for(auto uu : g[v])
    if(uu.f != p)
     ans[v] = max(ans[v] , ans[uu.f]) ;

  for(auto x : smalls){
    vec[v].pb(x) ;
    maxh[va[x]] = max(maxh[va[x]] , h[x]) ;
  }

  if(keep == 0){
    for(auto x : vec[v])
      maxh[va[x]] = 0;
  }
}

int main()
{
 std::ios::sync_with_stdio(0) ;
 cin.tie(0) ;
 cout.tie(0);

 cin >> n ;
 for(int i = 2 ; i <= n ; i ++){
    ll v ;
    char ch ;
    cin >> v >> ch ;
    g[v].pb({i , ch}) ;
    g[i].pb({v , ch}) ;
 }
 h[1] = 1 ;
 dfs(1 , 0 , 0) ;

 gooni(1 , 0 , 1) ;

 for(int i = 1 ;i <= n ; i ++)cout << ans[i] << " " ;

    return 0;
}


#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 5e5 + 10, M = 45e5;
int head[N], ver[N << 1], Next[N << 1], edge[N << 1], tot;
int n, son[N], d[N], mxd[M], s[N], dfn[N], a[N], b[N], num, ans[N], mp[N];

inline void add(int x, int y, int z) {
    ver[++tot] = y;
    Next[tot] = head[x];
    edge[tot] = z;
    head[x] = tot;
}

inline void read() {
    n = qr();
    repi(y, 2, n) {
        int x = qr();
        char z = getchar();
        add(x, y, 1 << (z - 'a'));
        add(y, x, 1 << (z - 'a'));
    }
}

void dfs(int x, int f) {
    dfn[x] = ++num, mp[num] = x, s[x] = 1;
    reps(x) {
        int y = ver[i], z = edge[i];
        if (y == f)continue;
        d[y] = d[x] + 1, b[y] = b[x] ^ z;
        dfs(y, x), s[x] += s[y];
        son[x] = s[y] > s[son[x]] ? y : son[x];
    }
}

void dfs(int x, int f, bool k) {
    reps(x) {
        int y = ver[i];
        if (y != f && y != son[x])
            dfs(y, x, false), ans[x] = max(ans[x], ans[y]);
    }
    if (son[x])dfs(son[x], x, true), ans[x] = max(ans[x], ans[son[x]]);
    ans[x] = max(ans[x], mxd[b[x]] - d[x]);
    repi(i, 0, 21)ans[x] = max(ans[x], mxd[b[x] ^ (1 << i)] - d[x]);
    mxd[b[x]] = max(mxd[b[x]], d[x]);
    reps(x) {
        int y = ver[i];
        if (y == f || y == son[x])continue;
        repi(j, dfn[y], dfn[y] + s[y] - 1) {
            if (mxd[a[j]])ans[x] = max(ans[x], d[mp[j]] + mxd[a[j]] - 2 * d[x]);
            repi(l, 0, 21)if (mxd[a[j] ^ (1 << l)])
                    ans[x] = max(ans[x], d[mp[j]] + mxd[a[j] ^ (1 << l)] - 2 * d[x]);
        }
        repi(j, dfn[y], dfn[y] + s[y] - 1)mxd[a[j]] = max(mxd[a[j]], d[mp[j]]);
    }
    if (!k)repi(i, dfn[x], dfn[x] + s[x] - 1)mxd[a[i]] = 0;
}

int main() {
    read();
    dfs(1, 0);
    repi(i, 1, n)a[dfn[i]] = b[i];
    dfs(1, 0, true);
    repi(i, 1, n)printf("%d%c", ans[i], ce(i, n));
    return 0;
}


#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 5e5 + 10, M = 45e5;
int head[N], ver[N << 1], Next[N << 1], edge[N << 1], tot;
int n, son[N], d[N], mxd[M], s[N], dfn[N], a[N], b[N], num, ans[N], mp[N];

inline void add(int x, int y, int z) {
    ver[++tot] = y;
    Next[tot] = head[x];
    edge[tot] = z;
    head[x] = tot;
}

inline void read() {
    n = qr();
    repi(y, 2, n) {
        int x = qr();
        char z = getchar();
        add(x, y, 1 << (z - 'a'));
        add(y, x, 1 << (z - 'a'));
    }
}

void dfs(int x, int f) {
    dfn[x] = ++num, mp[num] = x,s[x]=1;
    reps(x) {
        int y = ver[i], z = edge[i];
        if (y == f)continue;
        d[y] = d[x] + 1, b[y] = b[x] ^ z;
        dfs(y, x), s[x] += s[y];
        son[x] = s[y] > s[son[x]] ? y : son[x];
    }
}

void dfs(int x, int f, bool k) {
    reps(x) {
        int y = ver[i];
        if (y != f && y != son[x])
            dfs(y, x, false), ans[x] = max(ans[x], ans[y]);
    }
    if (son[x])dfs(son[x], x, true), ans[x] = max(ans[x], ans[son[x]]);
    if (mxd[b[x]])ans[x] = max(ans[x], mxd[b[x]] - d[x]);
    repi(i, 0, 21)if(mxd[b[x]^(1<<i)])ans[x] = max(ans[x], mxd[b[x] ^ (1 << i)] - d[x]);
    mxd[b[x]] = max(mxd[b[x]], d[x]);
    reps(x) {
        int y = ver[i];
        if (y == f || y == son[x])continue;
        repi(j, dfn[y], dfn[y] + s[y] - 1) {
            if (mxd[a[j]])ans[x] = max(ans[x], d[mp[j]] + mxd[a[j]] - 2 * d[x]);
            repi(l, 0, 21)if (mxd[a[j] ^ (1 << l)])
                    ans[x] = max(ans[x], d[mp[j]] + mxd[a[j] ^ (1 << l)] - 2 * d[x]);
        }
        repi(j, dfn[y], dfn[y] + s[y] - 1)mxd[a[j]] = max(mxd[a[j]], d[mp[j]]);
    }
    if (!k)repi(i, dfn[x], dfn[x] + s[x] - 1)mxd[a[i]] = 0;
}

int main() {
    read();
    dfs(1, 0);
    repi(i, 1, n)a[dfn[i]] = b[i];
    dfs(1, 0, true);
    repi(i, 1, n)printf("%d%c", ans[i], ce(i, n));
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define MAXN 500000
using namespace std;
struct edge
{
	int to;
	char val;
	edge(){};
	edge(int _to,char _val):to(_to),val(_val){};
};
int ans[MAXN+5],f[(1<<23)+5],col[MAXN+5];
int dep[MAXN+5],siz[MAXN+5],bigson[MAXN+5];
vector<edge> G[MAXN+5];
void prepare(int u,int fa)
{
	int maxsiz=-1;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		char w=G[u][i].val;
		if(v==fa)
			continue;
		dep[v]=dep[u]+1;
		col[v]=(col[u]^(1<<(w-'a')));
		f[col[v]]=max(f[col[v]],dep[v]);
		prepare(v,u);
		siz[u]+=siz[v];
		if(siz[v]>maxsiz)
		{
			maxsiz=siz[v];
			bigson[u]=v;
		}
	}
}
void Clear(int u,int fa)
{
	f[col[u]]=0;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		if(v==fa)
			continue;
		Clear(v,u);
	}
}
void Check(int u,int fa,int rt)
{
	if(f[col[u]]!=0)
		ans[rt]=max(ans[rt],f[col[u]]+dep[u]-2*dep[rt]);
	for(int i='a';i<='v';i++)
		if(f[col[u]^(1<<(i-'a'))]!=0)
			ans[rt]=max(ans[rt],f[col[u]^(1<<(i-'a'))]+dep[u]-2*dep[rt]);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		if(v==fa)
			continue;
		Check(v,u,rt);
	}
}
void Add(int u,int fa)
{
	f[col[u]]=max(dep[u],f[col[u]]);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		if(v==fa)
			continue;
		Add(v,u);
	}
}
void DFS(int u,int fa)
{
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		if(v==fa||v==bigson[u])
			continue;
		DFS(v,u);
		Clear(v,u);
	}
	if(bigson[u]!=0)
		DFS(bigson[u],u);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		ans[u]=max(ans[u],ans[v]);
		if(v==fa||v==bigson[u])
			continue;
		Check(v,u,u);
		Add(v,u);
	}
	if(f[col[u]]!=0)
		ans[u]=max(ans[u],f[col[u]]-dep[u]);
	for(int i='a';i<='v';i++)
		if(f[col[u]^(1<<(i-'a'))]!=0)
			ans[u]=max(ans[u],f[col[u]^(1<<(i-'a'))]-dep[u]);
	f[col[u]]=max(f[col[u]],dep[u]);
}
int main()
{
	int n,x;
	char s[10];
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d %s",&x,s);
		G[x].push_back(edge(i+1,s[0]));
		G[i+1].push_back(edge(x,s[0]));
	}
	prepare(1,-1);
	DFS(1,-1);
	for(int i=1;i<=n;i++)
		if(i==1)
			printf("%d",ans[i]);
		else
			printf(" %d",ans[i]);
	printf("\n");
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define MAXN 500000
using namespace std;
struct edge
{
	int to;
	char val;
	edge(){};
	edge(int _to,char _val):to(_to),val(_val){};
};
int ans[MAXN+5],f[(1<<23)+5],col[MAXN+5];
int dep[MAXN+5],siz[MAXN+5],bigson[MAXN+5];
vector<edge> G[MAXN+5];
void prepare(int u)
{
	int maxsiz=-1;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		char w=G[u][i].val;
		dep[v]=dep[u]+1;
		col[v]=(col[u]^(1<<(w-'a')));
		prepare(v);
		siz[u]+=siz[v];
		if(siz[v]>maxsiz)
		{
			maxsiz=siz[v];
			bigson[u]=v;
		}
	}
}
void Clear(int u)
{
	f[col[u]]=0;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		Clear(v);
	}
}
void Check(int u,int rt)
{
	if(f[col[u]]!=0)
		ans[rt]=max(ans[rt],f[col[u]]+dep[u]-2*dep[rt]);
	for(int i='a';i<='v';i++)
		if(f[col[u]^(1<<(i-'a'))]!=0)
			ans[rt]=max(ans[rt],f[col[u]^(1<<(i-'a'))]+dep[u]-2*dep[rt]);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		Check(v,rt);
	}
}
void Add(int u)
{
	f[col[u]]=max(dep[u],f[col[u]]);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		Add(v);
	}
}
void DFS(int u)
{
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		if(v==bigson[u])
			continue;
		DFS(v);
		Clear(v);
	}
	if(bigson[u]!=0)
		DFS(bigson[u]);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		ans[u]=max(ans[u],ans[v]);
		if(v==bigson[u])
			continue;
		Check(v,u);
		Add(v);
	}
	if(f[col[u]]!=0)
		ans[u]=max(ans[u],f[col[u]]-dep[u]);
	for(int i='a';i<='v';i++)
		if(f[col[u]^(1<<(i-'a'))]!=0)
			ans[u]=max(ans[u],f[col[u]^(1<<(i-'a'))]-dep[u]);
	f[col[u]]=max(f[col[u]],dep[u]);
}
int main()
{
	int n,x;
	char s[10];
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d %s",&x,s);
		G[x].push_back(edge(i+1,s[0]));
	}
	prepare(1);
	DFS(1);
	for(int i=1;i<=n;i++)
		if(i==1)
			printf("%d",ans[i]);
		else
			printf(" %d",ans[i]);
	printf("\n");
	return 0;
}
/*
10
1 d
1 d
2 d
3 e
1 d
1 d
2 b
7 e
4 c

*/


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define MAXN 500000
#define MAXS 7000000
using namespace std;
struct edge
{
	int to;
	char w;
	edge *nxt;
}edges[MAXN+5];
edge *ncnt=&edges[0],*Adj[MAXN+5];
int n,siz[MAXN+5],son[MAXN+5];
int st[MAXN+5],ans[MAXN+5],dep[MAXN+5];
map<int,int> mp;
void AddEdge(int u,int v,char w)
{
	edge *p=++ncnt;
	p->to=v;p->w=w;
	p->nxt=Adj[u];Adj[u]=p;
}
void PreDFS(int u)
{
	siz[u]=1;
	for(edge *p=Adj[u];p!=NULL;p=p->nxt)
	{
		int v=p->to;int w=p->w-'a';
		st[v]=(st[u]^(1<<w));
		dep[v]=dep[u]+1;
		PreDFS(v);
		siz[u]+=siz[v];
		if(son[u]==0||siz[v]>siz[son[u]])
			son[u]=v;
	}
}
void DFS1(int u,int rt)
{
	int st1=st[u],st2=st[u];
	if(mp.find(st2)!=mp.end())
		ans[rt]=max(ans[rt],dep[u]-dep[rt]+mp[st2]-dep[rt]);
	for(int i=0;i<26;i++)
	{
		st2=(1<<i)^st1;
		if(mp.find(st2)!=mp.end())
			ans[rt]=max(ans[rt],dep[u]-dep[rt]+mp[st2]-dep[rt]);
	}
	for(edge *p=Adj[u];p!=NULL;p=p->nxt)
	{
		int v=p->to;
		DFS1(v,rt);
	}
}
void DFS2(int u,int rt)
{
	mp[st[u]]=max(mp[st[u]],dep[u]);
	for(edge *p=Adj[u];p!=NULL;p=p->nxt)
	{
		int v=p->to;
		DFS2(v,rt);
	}
}
void DFS(int u)
{
	for(edge *p=Adj[u];p!=NULL;p=p->nxt)
	{
		int v=p->to;
		if(v!=son[u])
			DFS(v),mp.clear();
	}
	mp[st[u]]=dep[u];
	if(son[u])
	{
		DFS(son[u]);
		int st1=st[u],st2;
		for(int i=0;i<26;i++)
		{
			st2=(1<<i)^st1;
			if(mp.find(st2)!=mp.end())
				ans[u]=max(ans[u],mp[st2]-dep[u]);
		}
		if(mp.find(st[u])!=mp.end())
			ans[u]=max(ans[u],mp[st[u]]-dep[u]);
	}
	for(edge *p=Adj[u];p!=NULL;p=p->nxt)
	{
		int v=p->to;
		if(v!=son[u])
		{
			ans[u]=max(ans[u],ans[v]);
			DFS1(v,u);
			DFS2(v,u);
		}
	}
}
int main()
{
	scanf("%d",&n);
	int u;char str[5];
	for(int i=2;i<=n;i++)
	{
		scanf("%d %s",&u,str);
		AddEdge(u,i,str[0]);
	}
	PreDFS(1);
	DFS(1);
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define MAXN 500000
using namespace std;
struct edge
{
	int to;
	char chr;
	edge(){};
	edge(int _to,char _chr):to(_to),chr(_chr){};
};
vector<edge> G[MAXN+5];
map<int,int> mp[MAXN+5];
map<int,int> mp2;
int ncnt=0,ID[MAXN+5],ans[MAXN+5];
int n;
int LowBit(int i){return i&(-i);}
bool leaf[MAXN+5];
int Count(int st)
{
	int ret=0;
	while(st)
	{
		ret++;
		st-=LowBit(st);
	}
	return ret;
}
void Add(int u,int st,int val,bool typ)
{
	if(Count(st)<=1)
		ans[u]=max(ans[u],val);
	int stn=st;
	map<int,int>::iterator it;
	if(typ==0)
	{
		it=mp[ID[u]].find(stn);
		if(it!=mp[ID[u]].end())
			ans[u]=max(it->second+val,ans[u]);
		for(int i='a';i<='v';i++)
		{
			stn=(st^(1<<(i-'a')));
			it=mp[ID[u]].find(stn);
			if(it==mp[ID[u]].end())
				continue;
			ans[u]=max(it->second+val,ans[u]);
		}
	}
	else if(typ==1)
		mp[ID[u]][st]=max(mp[ID[u]][st],val);
}
void DFS(int u,int fa)
{
	int maxsiz=-1,maxpos;
	char maxch;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		char w=G[u][i].chr;
		if(v==fa)
			continue;
		DFS(v,u);
		if(maxsiz<(int)mp[ID[v]].size())
		{
			maxsiz=mp[ID[v]].size();
			maxpos=v;
			maxch=w;
		}
	}
	if(maxsiz==-1)
	{
		leaf[u]=true;
		ID[u]=++ncnt;
		mp[ID[u]][0]=0;
		return;
	}
	ans[u]=ans[maxpos];
	ID[u]=ID[maxpos];
	map<int,int>::iterator it;
	mp2.clear();
	for(it=mp[ID[maxpos]].begin();it!=mp[ID[maxpos]].end();it++)
		mp2[it->first^(1<<(maxch-'a'))]=it->second+1;
	mp[ID[maxpos]].clear();
	for(it=mp2.begin();it!=mp2.end();it++)
		if(leaf[maxpos]==false)
			Add(u,it->first,it->second,1);
		else
		{
			Add(u,it->first,it->second,0);
			Add(u,it->first,it->second,1);
		}
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].to;
		char w=G[u][i].chr;
		if(v==fa||v==maxpos)
			continue;
		for(it=mp[ID[v]].begin();it!=mp[ID[v]].end();it++)
			Add(u,((it->first)^(1<<(w-'a'))),it->second+1,0);
		for(it=mp[ID[v]].begin();it!=mp[ID[v]].end();it++)
			Add(u,((it->first)^(1<<(w-'a'))),it->second+1,1);
	}
}
int main()
{
	scanf("%d",&n);
	char s[10];
	int x;
	for(int i=1;i<n;i++)
	{
		scanf("%d %s",&x,s);
		G[x].push_back(edge(i+1,s[0]));
		G[i+1].push_back(edge(x,s[0]));
	}
	DFS(1,-1);
	for(int i=1;i<=n;i++)
		if(i==1)
			printf("%d",ans[i]);
		else
			printf(" %d",ans[i]);
	printf("\n");
	return 0;
}