#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 5;
struct SAM {
  int Go[26], fail, Len;
  long long Val;
} A[MAXN * 2];
char S[MAXN], T[MAXN];
int N, tot, Start[MAXN], Root, p, Val, Ord[MAXN * 2];
void Add(int ch) {
  int np = ++tot;
  A[np].Len = A[p].Len + 1;
  for (; p && !A[p].Go[ch]; p = A[p].fail) A[p].Go[ch] = np;
  if (!p)
    A[np].fail = Root;
  else {
    int q = A[p].Go[ch];
    if (A[p].Len + 1 == A[q].Len)
      A[np].fail = q;
    else {
      int nq = ++tot;
      A[nq] = A[q];
      A[q].fail = A[np].fail = nq;
      A[nq].Len = A[p].Len + 1;
      for (; p && A[p].Go[ch] == q; p = A[p].fail) A[p].Go[ch] = nq;
    }
  }
  p = np;
}
bool Cmp(int x, int y) { return A[x].Len > A[y].Len; }
void Solve() {
  for (int i = 1; i <= N; i++) {
    scanf("%d", &Val);
    p = 1;
    for (int j = Start[i]; j < Start[i + 1]; j++) {
      p = A[p].Go[T[j] - 'a'];
      A[p].Val += Val;
    }
  }
  for (int i = 1; i <= tot; i++) Ord[i] = i;
  sort(Ord + 1, Ord + 1 + tot, Cmp);
  for (int i = 1; i <= tot; i++) {
    int Now = Ord[i];
    A[A[Now].fail].Val += A[Now].Val;
  }
  long long Ans = 0;
  for (int i = 1; i <= tot; i++) Ans = max(Ans, A[i].Val * A[i].Len);
  printf("%I64d", Ans);
}
int main() {
  scanf("%d", &N);
  tot = 0;
  for (int i = 1; i <= N; i++) {
    Start[i] = tot + 1;
    char ch = getchar();
    while (ch < 'a' || ch > 'z') ch = getchar();
    while (ch >= 'a' && ch <= 'z') T[++tot] = ch, ch = getchar();
  }
  Start[N + 1] = tot + 1;
  Root = tot = 1;
  for (int i = 1; i <= N; i++) {
    p = 1;
    for (int j = Start[i]; j < Start[i + 1]; j++) Add(T[j] - 'a');
  }
  Solve();
}
