#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
template<class T, class T2> inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; }
template<class T, class T2> inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; }
const int MAXN = (1 << 20);

struct suffix_automaton
{
	map<char, int> to[MAXN];
	int len[MAXN], link[MAXN];
	int last, psz = 0;

	void add_letter(char c)
	{
		int p = last, cl, q;
		if(to[p].count(c))
		{
  			q = to[p][c];
			if(len[q] == len[p] + 1)
			{
				last = q;
				return;
			}

			cl = psz++;
			len[cl] = len[p] + 1;
			to[cl] = to[q];
			link[cl] = link[q];
			link[q] = cl;
			last = cl;
	
			for(; to[p][c] == q; p = link[p])
				to[p][c] = cl;
			
			return;
		}

		last = psz++;
		len[last] = len[p] + 1;

		for(; to[p][c] == 0; p = link[p])
			to[p][c] = last;
	
		if(to[p][c] == last) 
		{
			link[last] = p;
			return;
		}

		q = to[p][c];
		if(len[q] == len[p] + 1)
		{
			link[last] = q;
			return;
		}

		cl = psz++;
		len[cl] = len[p] + 1;
		to[cl] = to[q];
		link[cl] = link[q];
		link[q] = cl;
		link[last] = cl;

		for(; to[p][c] == q; p = link[p])
			to[p][c] = cl;
	}

	void clear()
	{
		for(int i = 0; i < psz; i++)
			len[i] = 0, link[i] = 0, to[i].clear();
		psz = 1;
		last = 0;
	}

	void init(string s)
	{
		clear();
		for(int i = 0; i < (int)s.size(); i++)
			add_letter(s[i]);
	}
	
	suffix_automaton() { memset(link, 0, sizeof(link)); memset(len, 0, sizeof(len)); clear();}
};

int n;
vector<int> G[MAXN];
string s[MAXN];

void read()
{
	cin >> n;
	for(int i = 2; i <= n; i++)
	{
		int p;
		cin >> p;
		G[p].push_back(i);
	}

	for(int i = 1; i <= n; i++)
		cin >> s[i];
}

int tr_sz[MAXN];
suffix_automaton sa;
int answer = -1;

void pre_dfs(int u, int pr)
{
	tr_sz[u] = s[u].size();
	for(int v: G[u])
		if(v != pr)
		{
			pre_dfs(v, u);
			tr_sz[u] += tr_sz[v];
		}
}

void add_vertex(int u)
{
	sa.last = 0;
	for(auto it: s[u])
		sa.add_letter(it);
}

void check_vertex(int u)
{
	int x = 0, l = 0;
	for(auto c: s[u])
	{
		while(x != 0 && !sa.to[x].count(c)) x = sa.link[x], l = sa.len[x];
		if(sa.to[x].count(c)) l++, x = sa.to[x][c];
		chkmax(answer, l);
	}
}

void add(int u, int pr)
{
	add_vertex(u);
	for(int v: G[u])
		if(v != pr)
			add(v, u);
}

void check(int u, int pr)
{
	check_vertex(u);
	for(int v: G[u])
		if(v != pr)
			check(v, u);
}

void dfs(int u, int pr, int keep)
{
	pair<int, int> mx = {-1, -1};
	for(int v: G[u])
		if(v != pr)
			mx = max(mx, {tr_sz[v], v});

	for(int v: G[u])
		if(v != pr && v != mx.second)
			dfs(v, u, 0);

	if(mx.second != -1)
		dfs(mx.second, u, 1);

	for(int v: G[u])
		if(v != pr && v != mx.second)
		{
			check(v, u);
			add(v, u);
		}

	add_vertex(u);

	if(keep) return;
	sa.clear();
}

void solve()
{
	sa.clear();
	pre_dfs(1, -1);
	dfs(1, -1, 1);
	cout << answer << endl;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	read();
	solve();
	return 0;
}