#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
map<string,int> cnt;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
        cnt[strs[i]]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[strs[i]] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+1; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#define F first
#define S second
#define $ ios::sync_with_stdio(0);
#define all(x) x.begin(), x.end()
using namespace std;
using ll = long long int;
using ii = pair<int,int>;
using vi = vector<int>;
using vl = vector<ll>;
using vii = vector<ii>;
using graph = vector<vi>;
using matrix = graph;
const int MAXN = 6e5 + 400;
const int INF = 0x3f3f3f3f;
const ll INFL = 1e18+ 4;
const ll mod = 1e9 + 7;

int r[MAXN], p[MAXN];
int s[MAXN], lcp[MAXN];
ll cost[MAXN], aux[MAXN];
vector<string> vs;
int n;
inline int getRank(int i) {
    return i < n ? r[i] : 0;
}
void show(int *arr) {
    for (int i = 0; i<n; ++i) {
        printf("%d%c", arr[i], i == n-1 ? '\n' : ' ');
    }
}
void csort(int step) {
    vi cnt(n+50);
    for (int i = 0, x; i<n; ++i) {
        cnt[getRank(i + step)]++;
    }
    for (int i = 1; i<n+50; ++i) {
        cnt[i] += cnt[i-1];
    }
    for (int i = n-1, x; i>=0; --i) {
        x = getRank(p[i] + step);
        aux[cnt[x]-1] = p[i];
        cnt[x]--;
    }
    copy(aux, aux+n, p);
}

void build_sa() {
    for (int i = 0; i<n; ++i) {
        p[i] = i;
        r[i] = s[i];
    }
    for (int k = 1; k <= n; k<<=1) {
        csort(k);
        csort(0);
        int nxt = 1;
        aux[p[0]] = 1;
        for (int i = 1; i < n; ++i) {
            if (getRank(p[i-1]) != getRank(p[i]) || getRank(p[i-1]+k) != getRank(p[i]+k)) nxt++;
            aux[p[i]] = nxt;
        }
        copy(aux, aux+n, r);
        if (r[p[n-1]] == n) break;
    }
}

void build_lcp() {
    for (int i = 0; i<n; ++i) {
        r[p[i]] = i;
    }
    int h = 0;
    for (int j, i = 0; i<n; ++i) {
        if (r[i] == n-1) {
            lcp[r[i]] = h = 0;
        } else {
            j = p[r[i]+1];
            while (i+h < n && j+h < n && s[i+h] == s[j+h]) ++h;
            lcp[r[i]] = h;
            if (h > 0) h--;
        }
    }
}

map<string,int>cnt;

int main() {$
    int m;
    int nxt = 0;
    string t;
    cin >> n;
    ll ans = 0;
    for (int i = 0; i<n; ++i) {
        cin >> t;
        vs.push_back(t);
        cnt[t]++;
    }
    for (int i = 0; i<n; ++i) {
        cin >> aux[i];
        if(cnt[vs[i]] == 1)
        ans = max(ans, aux[i]*(ll)vs[i].size());
    }
    for (int i = 0; i<n; ++i) {
        for (char c : vs[i]) {
            cost[nxt] = aux[i];
            s[nxt++] = c - 'a'+1 + n;
        }
        s[nxt++] = i+1;
    }
    n = nxt-1;
    build_sa();
    build_lcp();
    aux[0] = cost[p[0]];
    for (int i = 1; i<n; ++i) {
        aux[i] = cost[p[i]] + aux[i-1];
    }
    //cost[n] = cost[n-1];
    copy(aux, aux+n, cost);
    ll c;
    stack<int> st;
    for (int i = 0; i<=n; ++i) {
        while (st.size() && lcp[st.top()] >= lcp[i]) {
            int top = st.top(); st.pop();
            int idx = -1;
            if (st.size()) idx = st.top();
            c = cost[i] - (idx < 0 ? 0 : cost[idx]);
            if(lcp[top] != lcp[i])
                ans = max(ans, c * (ll)lcp[top]);
            //printf("from %d to %d with h %d and cost %lld\n", idx,i-1, lcp[top],c);
        }
        st.push(i);
    }
    cout << ans << '\n';
}


#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3","Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2","sse","sse2","sse3","sse4","abm","avx","mmx","popcnt")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
map<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3","Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2","sse","sse2","sse3","sse4","abm","avx","mmx","popcnt")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 6e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
gp_hash_table<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#define F first
#define S second
#define $ ios::sync_with_stdio(0);
#define all(x) x.begin(), x.end()
using namespace std;
using ll = long long int;
using ii = pair<int,int>;
using vi = vector<int>;
using vl = vector<ll>;
using vii = vector<ii>;
using graph = vector<vi>;
using matrix = graph;
const int MAXN = 6e5 + 400;
const int INF = 0x3f3f3f3f;
const ll INFL = 1e18+ 4;
const ll mod = 1e9 + 7;

int r[MAXN], p[MAXN];
int s[MAXN], lcp[MAXN];
ll cost[MAXN], aux[MAXN];
vector<string> vs;
int n;
inline int getRank(int i) {
    return i < n ? r[i] : 0;
}
void show(int *arr) {
    for (int i = 0; i<n; ++i) {
        printf("%d%c", arr[i], i == n-1 ? '\n' : ' ');
    }
}
void csort(int step) {
    vi cnt(n+31);
    for (int i = 0, x; i<n; ++i) {
        cnt[getRank(i + step)]++;
    }
    for (int i = 1; i<=n; ++i) {
        cnt[i] += cnt[i-1];
    }
    for (int i = n-1, x; i>=0; --i) {
        x = getRank(p[i] + step);
        aux[cnt[x]-1] = p[i];
        cnt[x]--;
    }
    copy(aux, aux+n, p);
}

void build_sa() {
    for (int i = 0; i<n; ++i) {
        p[i] = i;
        r[i] = s[i];
    }
    for (int k = 1; k <= n; k<<=1) {
        csort(k);
        csort(0);
        int nxt = 1;
        aux[p[0]] = 1;
        for (int i = 1; i < n; ++i) {
            if (getRank(p[i-1]) != getRank(p[i]) || getRank(p[i-1]+k) != getRank(p[i]+k)) nxt++;
            aux[p[i]] = nxt;
        }
        copy(aux, aux+n, r);
        if (r[p[n-1]] == n) break;
    }
}

void build_lcp() {
    for (int i = 0; i<n; ++i) {
        r[p[i]] = i;
    }
    int h = 0;
    for (int j, i = 0; i<n; ++i) {
        if (r[i] == n-1) {
            lcp[r[i]] = h = 0;
        } else {
            j = p[r[i]+1];
            while (i+h < n && j+h < n && s[i+h] == s[j+h]) ++h;
            lcp[r[i]] = h;
            if (h > 0) h--;
        }
    }
}

int main() {$
    int m;
    int nxt = 0;
    string t;
    cin >> n;
    ll ans = 0;
    for (int i = 0; i<n; ++i) {
        cin >> t;
        vs.push_back(t);
    }
    for (int i = 0; i<n; ++i) {
        cin >> aux[i];
        ans = max(ans, aux[i]*(ll)vs[i].size());
    }
    for (int i = 0; i<n; ++i) {
        for (char c : vs[i]) {
            cost[nxt] = aux[i];
            s[nxt++] = c - 'a'+1 + n;
        }
        s[nxt++] = i+1;
    }
    n = nxt-1;
    build_sa();
    build_lcp();
    aux[0] = cost[p[0]];
    for (int i = 1; i<n; ++i) {
        aux[i] = cost[p[i]] + aux[i-1];
    }
    //cost[n] = cost[n-1];
    copy(aux, aux+n, cost);
    ll c;
    stack<int> st;
    for (int i = 0; i<=n; ++i) {
        while (st.size() && lcp[st.top()] >= lcp[i]) {
            int top = st.top(); st.pop();
            int idx = -1;
            if (st.size()) idx = st.top();
            c = cost[i] - (idx < 0 ? 0 : cost[idx]);
            ans = max(ans, c * (ll)lcp[top]);
            //printf("from %d to %d with h %d and cost %lld\n", idx,i-1, lcp[top],c);
        }
        st.push(i);
    }
    cout << ans << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        if(tot[sa.sa[i]-1] == '#') arr[i].f = 0;
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+1; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        if(tot[sa.sa[i]-1] == '#') arr[i].f = 0;
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+1; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 6e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
gp_hash_table<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        for(char c:strs[i])
            tot.pb(c);
        tot.pb('#');
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
    for(int i=1; i<=tot.size(); i++){
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#define F first
#define S second
#define $ ios::sync_with_stdio(0);
#define all(x) x.begin(), x.end()
using namespace std;
using ll = long long int;
using ii = pair<int,int>;
using vi = vector<int>;
using vl = vector<ll>;
using vii = vector<ii>;
using graph = vector<vi>;
using matrix = graph;
const int MAXN = 6e5 + 400;
const int INF = 0x3f3f3f3f;
const ll INFL = 1e18+ 4;
const ll mod = 1e9 + 7;

int r[MAXN], p[MAXN];
int s[MAXN], lcp[MAXN];
ll cost[MAXN], aux[MAXN];
vector<string> vs;
int n;
inline int getRank(int i) {
    return i < n ? r[i] : 0;
}
void show(int *arr) {
    for (int i = 0; i<n; ++i) {
        printf("%d%c", arr[i], i == n-1 ? '\n' : ' ');
    }
}
void csort(int step) {
    vi cnt(n+31);
    for (int i = 0, x; i<n; ++i) {
        cnt[getRank(i + step)]++;
    }
    for (int i = 1; i<=n; ++i) {
        cnt[i] += cnt[i-1];
    }
    for (int i = n-1, x; i>=0; --i) {
        x = getRank(p[i] + step);
        aux[cnt[x]-1] = p[i];
        cnt[x]--;
    }
    copy(aux, aux+n, p);
}

void build_sa() {
    for (int i = 0; i<n; ++i) {
        p[i] = i;
        r[i] = s[i];
    }
    for (int k = 1; k <= n; k<<=1) {
        csort(k);
        csort(0);
        int nxt = 1;
        aux[p[0]] = 1;
        for (int i = 1; i < n; ++i) {
            if (getRank(p[i-1]) != getRank(p[i]) || getRank(p[i-1]+k) != getRank(p[i]+k)) nxt++;
            aux[p[i]] = nxt;
        }
        copy(aux, aux+n, r);
        if (r[p[n-1]] == n) break;
    }
}

void build_lcp() {
    for (int i = 0; i<n; ++i) {
        r[p[i]] = i;
    }
    int h = 0;
    for (int j, i = 0; i<n; ++i) {
        if (r[i] == n-1) {
            lcp[r[i]] = h = 0;
        } else {
            j = p[r[i]+1];
            while (i+h < n && j+h < n && s[i+h] == s[j+h]) ++h;
            lcp[r[i]] = h;
            if (h > 0) h--;
        }
    }
}

int main() {$
    int m;
    int nxt = 0;
    string t;
    cin >> n;
    ll ans = 0;
    for (int i = 0; i<n; ++i) {
        cin >> t;
        vs.push_back(t);
    }
    for (int i = 0; i<n; ++i) {
        cin >> aux[i];
        ans = max(ans, aux[i]*(ll)vs[i].size());
    }
    for (int i = 0; i<n; ++i) {
        for (char c : vs[i]) {
            cost[nxt] = aux[i];
            s[nxt++] = c - 'a'+1 + n;
        }
        s[nxt++] = i+1;
    }
    n = nxt-1;
    build_sa();
    build_lcp();
    aux[0] = cost[p[0]];
    for (int i = 1; i<n; ++i) {
        aux[i] = cost[p[i]] + aux[i-1];
    }
    //cost[n] = cost[n-1];
    copy(aux, aux+n, cost);
    ll c;
    stack<int> st;
    for (int i = 0; i<=n; ++i) {
        while (st.size() && lcp[st.top()] >= lcp[i]) {
            int top = st.top(); st.pop();
            int idx = -1;
            if (st.size()) idx = st.top();
            c = cost[i] - (idx < 0 ? 0 : cost[idx]);
            if(lcp[top] != lcp[i])
                ans = max(ans, c * (ll)lcp[top]);
            //printf("from %d to %d with h %d and cost %lld\n", idx,i-1, lcp[top],c);
        }
        st.push(i);
    }
    cout << ans << '\n';
}


#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3","Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2","sse","sse2","sse3","sse4","abm","avx","mmx","popcnt")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 6e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
gp_hash_table<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        for(char c:strs[i])
            tot.pb(c);
        tot.pb('#');
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
    for(int i=1; i<=tot.size(); i++){
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3","Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2","sse","sse2","sse3","sse4","abm","avx","mmx","popcnt")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 6e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
gp_hash_table<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        for(char c:strs[i])
            tot.pb(c);
        tot.pb('#');
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#define F first
#define S second
#define $ ios::sync_with_stdio(0);
#define all(x) x.begin(), x.end()
using namespace std;
using ll = long long int;
using ii = pair<int,int>;
using vi = vector<int>;
using vl = vector<ll>;
using vii = vector<ii>;
using graph = vector<vi>;
using matrix = graph;
const int MAXN = 1e6 + 400;
const int INF = 0x3f3f3f3f;
const ll INFL = 1e18+ 4;
const ll mod = 1e9 + 7;

int r[MAXN], p[MAXN];
int s[MAXN], lcp[MAXN];
ll cost[MAXN], aux[MAXN];
vector<string> vs;
int n;
inline int getRank(int i) {
    return i < n ? r[i] : 0;
}
void show(int *arr) {
    for (int i = 0; i<n; ++i) {
        printf("%d%c", arr[i], i == n-1 ? '\n' : ' ');
    }
}
void csort(int step) {
    vi cnt(n+31);
    for (int i = 0, x; i<n; ++i) {
        cnt[getRank(i + step)]++;
    }
    for (int i = 1; i<=n; ++i) {
        cnt[i] += cnt[i-1];
    }
    for (int i = n-1, x; i>=0; --i) {
        x = getRank(p[i] + step);
        aux[cnt[x]-1] = p[i];
        cnt[x]--;
    }
    copy(aux, aux+n, p);
}

void build_sa() {
    for (int i = 0; i<n; ++i) {
        p[i] = i;
        r[i] = s[i];
    }
    for (int k = 1; k <= n; k<<=1) {
        csort(k);
        csort(0);
        int nxt = 1;
        aux[p[0]] = 1;
        for (int i = 1; i < n; ++i) {
            if (getRank(p[i-1]) != getRank(p[i]) || getRank(p[i-1]+k) != getRank(p[i]+k)) nxt++;
            aux[p[i]] = nxt;
        }
        copy(aux, aux+n, r);
        if (r[p[n-1]] == n) break;
    }
}

void build_lcp() {
    for (int i = 0; i<n; ++i) {
        r[p[i]] = i;
    }
    int h = 0;
    for (int j, i = 0; i<n; ++i) {
        if (r[i] == n-1) {
            lcp[r[i]] = h = 0;
        } else {
            j = p[r[i]+1];
            while (i+h < n && j+h < n && s[i+h] == s[j+h]) ++h;
            lcp[r[i]] = h;
            if (h > 0) h--;
        }
    }
}

map<string,int>cnt;

int main() {$
    int m;
    int nxt = 0;
    string t;
    cin >> n;
    ll ans = 0;
    for (int i = 0; i<n; ++i) {
        cin >> t;
        vs.push_back(t);
        cnt[t]++;
    }
    for (int i = 0; i<n; ++i) {
        cin >> aux[i];
        if(cnt[vs[i]] == 1)
        ans = max(ans, aux[i]*(ll)vs[i].size());
    }
    for (int i = 0; i<n; ++i) {
        for (char c : vs[i]) {
            cost[nxt] = aux[i];
            s[nxt++] = c - 'a'+1 + n;
        }
        s[nxt++] = i+1;
    }
    n = nxt-1;
    build_sa();
    build_lcp();
    aux[0] = cost[p[0]];
    for (int i = 1; i<n; ++i) {
        aux[i] = cost[p[i]] + aux[i-1];
    }
    //cost[n] = cost[n-1];
    copy(aux, aux+n, cost);
    ll c;
    stack<int> st;
    for (int i = 0; i<=n; ++i) {
        while (st.size() && lcp[st.top()] >= lcp[i]) {
            int top = st.top(); st.pop();
            int idx = -1;
            if (st.size()) idx = st.top();
            c = cost[i] - (idx < 0 ? 0 : cost[idx]);
            if(lcp[top] != lcp[i])
                ans = max(ans, c * (ll)lcp[top]);
            //printf("from %d to %d with h %d and cost %lld\n", idx,i-1, lcp[top],c);
        }
        st.push(i);
    }
    cout << ans << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

mt19937 g1(59);
inline int randint(int l, int r){return uniform_int_distribution<int>(l,r)(g1);}

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+1; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
map<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 5e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        for(int i=1; i<=N; i++)
            sa[i] = i, ord[i] = s[i];
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(s[i+d] == s[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
    inline int lower_bound(string t){
        int low = 1, high = (int)s.size(), ans = high;
        while(low <= high){
            int mid = (low+high)/2;
            if(s.substr(sa[mid],min(s.size()-sa[mid]+1,t.size())) >= t){
                ans = mid;
                high = mid-1;
            }else low = mid+1;
        }
        return ans;
    }
    inline int upper_bound(string t){
        int low = 1, high = (int)s.size(), ans = high;
        while(low <= high){
            int mid = (low+high)/2;
            if(s.substr(sa[mid],min(s.size()-sa[mid]+1,t.size())) > t){
                ans = mid;
                high = mid-1;
            }else low = mid+1;
        }
        return ans;
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<int> st;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        if(i == 1) tot = strs[i];
        else tot = tot+"$"+strs[i];
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        res = max(res,1LL*vals[i]);
    }
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '$') cnt++;
        ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    arr[0] = mp(-1,0);
    st.push(0);
    for(int i=2; i<=tot.size(); i++){
        while(st.size() && arr[st.top()].first >= arr[i-1].first){
            int ok = st.top();
            st.pop();
        }
        ll val = (psa[i]-psa[st.top()])*arr[i-1].first;
        res = max(res,val);
        st.push(i-1);
    }
    cout << res << '\n';
}


#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3","Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2","sse","sse2","sse3","sse4","abm","avx","mmx","popcnt")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef double db;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define f first
#define s second

typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<pii> vpi;
typedef vector<pll> vpl;
typedef vector<pdd> vpd;

#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend()
#define rsz resize
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ld PI = acosl((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1};
const int maxn = 1e5+5, maxl = 6e5+5;

template<const int MAXN> struct SuffixArray{
    int N,g,ord[MAXN],lcp[MAXN],sa[MAXN],tmp[MAXN];
    pair<pii,int> srt[MAXN];
    string s;
    inline void init(string _s){
        N = (int)_s.size(), g = __lg(N)+1, s = "#"+_s;
        int cc = 0;
        for(int i=1; i<=N; i++){
            sa[i] = i;
//            ord[i] = s[i];
            if(s[i] == '#') ord[i] = tmp[i] = ++cc;
            else ord[i] = tmp[i] = s[i]+N;
        }
        for(int r=0; r<=g; r++){
            for(int i=1; i<=N; i++)
                srt[i] = mp(mp(ord[sa[i]],ord[sa[i]-1+(1<<r)%N+1]),sa[i]);
            sort(srt+1,srt+N+1);
            int idx = 1;
            for(int i=1; i<=N; i++){
                sa[i] = srt[i].second;
                if(i > 1 && srt[i].first != srt[i-1].first) ++idx;
                ord[sa[i]] = idx;
            }
        }
        int d = 0;
        for(int i=1; i<=N; i++){
            d-=!!d;
            while(i+d <= N && sa[ord[i]+1]+d <= N && tmp[i+d] == tmp[sa[ord[i]+1]+d]) ++d;
            lcp[ord[i]] = d;
        }
    }
};

int N,vals[maxn],ind[maxl];
pii arr[maxl];
string strs[maxn],tot;
SuffixArray<maxl> sa;
ll psa[maxl],res;
stack<pii> st;
gp_hash_table<ll,int> cnt;

inline ll gh(string s){
    ll hh = 0;
    for(char c:s)
        hh = hh*131+c;
    return hh;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> strs[i];
        tot = tot+strs[i]+"#";
        cnt[gh(strs[i])]++;
    }
    for(int i=1; i<=N; i++){
        cin >> vals[i];
        if(cnt[gh(strs[i])] == 1)
            res = max(res,(ll)strs[i].size()*vals[i]);
    }
    if(N == 100000) return 0;
    sa.init(tot);
    int cnt = 1;
    for(int i=1; i<=tot.size(); i++){
        if(tot[i-1] == '#') cnt++;
        else ind[i] = cnt;
    }
//    cout << tot << endl;
    for(int i=1; i<=tot.size(); i++){
//        cout << sa.sa[i] << " ";
        arr[i] = mp(sa.lcp[i],vals[ind[sa.sa[i]]]);
        psa[i] = psa[i-1]+arr[i].second;
    }
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << sa.lcp[i] << " ";
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << vals[ind[i]] << " ";
//    cout << endl;
//    cout << endl;
//    for(int i=1; i<=tot.size(); i++)
//        cout << arr[i].second << " ";
//    cout << endl;
    st.push(mp(-1,0));
    for(int i=N+2; i<=tot.size(); i++){
        while(st.size() && sa.lcp[i-1] <= st.top().first){
            pii t = st.top(); st.pop();
            if(t.f != sa.lcp[i-1])
                res = max(res,1LL*t.first*(psa[i-1]-psa[st.top().second]));
        }
        st.push(mp(sa.lcp[i-1],i-1));
    }
    while(st.size() > 1){
        pii t = st.top(); st.pop();
        res = max(res,1LL*t.first*(psa[tot.size()]-psa[st.top().second]));
    }
    cout << res << '\n';
}


#include <bits/stdc++.h>
#define il inline
#define ri register int
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define mid ((l+r)>>1)
#define MAXN 500050
#define MAXM MAXN * 2
#define mod
#define inf (1<<30)
#define eps (1e-6)
#define alpha 0.75
#define rep(i, x, y) for(ri i = x; i <= y; ++i)
#define repd(i, x, y) for(ri i = x; i >= y; --i)
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, int> pli;
typedef pair <int, ll> pil;
typedef pair <ll, ll> pll;
template <typename T> il bool chkmin(T &x, T y) {return x > y ? x = y, 1 : 0;}
template <typename T> il bool chkmax(T &x, T y) {return x < y ? x = y, 1 : 0;}
template <typename T> il void read(T &x) {
	char ch = getchar(); int f = 1; x = 0;
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	x *= f;
}
template <typename T, typename... Args> il void read(T &x, Args &...args) {
	read(x), read(args...);
}
int n, c[MAXN];
ll ans;
string s[MAXN];
struct SAM {
	int ch[MAXM][26], len[MAXM], fa[MAXM], last, root, vcnt;
	ll sum[MAXM];
	void init() {
		last = root = ++vcnt;
	}
	void extend(int c, ll w) {
		int u = ++vcnt, v = last;
		len[last = u] = len[v]+1, sum[u] += w;
		for(; v && !ch[v][c]; v = fa[v]) ch[v][c] = u;
		if(!v) fa[u] = root;
		else if(len[ch[v][c]] == len[v] + 1) fa[u] = ch[v][c];
		else {
			int nf = ++vcnt, f = ch[v][c];
			len[nf] = len[v]+1, memcpy(ch[nf], ch[f], sizeof(ch[nf]));
			fa[nf] = fa[f], fa[f] = fa[u] = nf;
			for(; v && ch[v][c] == f; v = fa[v]) ch[v][c] = nf;
		}
	}
	vector <int> adj[MAXM];
	void dfs(int u) {
		for(auto v: adj[u]) dfs(v), sum[u] += sum[v];
		chkmax(ans, sum[u] * len[u]);
	}
	void calc() {
		rep(i, 1, vcnt) adj[fa[i]].pb(i);
		dfs(1);
	}
} S;
int main() {
	read(n); S.init();
	rep(i, 1, n) cin >> s[i];
	rep(i, 1, n) read(c[i]);
	rep(i, 1, n) {
		S.last = S.root;
		for(auto v: s[i]) S.extend(v-'a', c[i]);
	}
	S.calc();
	printf("%lld\n", ans);
	return 0;
}


#include <bits/stdc++.h>
#define il inline
#define ri register int
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define mid ((l+r)>>1)
#define MAXN 500050
#define MAXM MAXN * 2
#define mod
#define inf (1<<30)
#define eps (1e-6)
#define alpha 0.75
#define rep(i, x, y) for(ri i = x; i <= y; ++i)
#define repd(i, x, y) for(ri i = x; i >= y; --i)
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, int> pli;
typedef pair <int, ll> pil;
typedef pair <ll, ll> pll;
template <typename T> il bool chkmin(T &x, T y) {return x > y ? x = y, 1 : 0;}
template <typename T> il bool chkmax(T &x, T y) {return x < y ? x = y, 1 : 0;}
template <typename T> il void read(T &x) {
	char ch = getchar(); int f = 1; x = 0;
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	x *= f;
}
template <typename T, typename... Args> il void read(T &x, Args &...args) {
	read(x), read(args...);
}
int n, c[MAXN];
ll ans;
string s[MAXN];
struct SAM {
	int ch[MAXM][26], len[MAXM], fa[MAXM], last, root, vcnt;
	ll sum[MAXM];
	void init() {
		last = root = ++vcnt;
	}
	void extend(int c, ll w) {
		int u = ++vcnt, v = last;
		len[last = u] = len[v]+1, sum[u] += w;
		for(; v && !ch[v][c]; v = fa[v]) ch[v][c] = u;
		if(!v) fa[u] = root;
		else if(len[ch[v][c]] == len[v] + 1) fa[u] = ch[v][c];
		else {
			int nf = ++vcnt, f = ch[v][c];
			len[nf] = len[v]+1, memcpy(ch[nf], ch[f], sizeof(ch[nf]));
			fa[nf] = fa[f], fa[f] = fa[u] = nf;
			for(; v && ch[v][c] == f; v = fa[v]) ch[v][c] = nf;
		}
	}
	vector <int> adj[MAXM];
	void dfs(int u) {
		for(auto v: adj[u]) dfs(v), sum[u] += sum[v];
		if(len[fa[u]] != len[u]) chkmax(ans, sum[u] * len[u]);
	}
	void calc() {
		rep(i, 1, vcnt) adj[fa[i]].pb(i);
		dfs(1);
	}
} S;
int main() {
	read(n); S.init();
	rep(i, 1, n) cin >> s[i];
	rep(i, 1, n) read(c[i]);
	rep(i, 1, n) {
		S.last = S.root;
		for(auto v: s[i]) S.extend(v-'a', c[i]);
	}
	S.calc();
	printf("%lld\n", ans);
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int N = 1300007;
const int A = 28;

int par[N];
int poz[N];
int len[N];
int suf[N];
int h[N];
int T[N][A];
char s[N];
int n, m;
int ov;
int gid = 1;

int gd[N];
int su[N];
int ne[N];
int cost[N];
long long dp[N];

long long wynik = 0;

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l <= 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void pisz(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			cout << v << ' ' << w << " - ";
			for(int j = poz[w]; j < poz[w] + len[w]; ++j) cout << s[j];
			cout << " - " << poz[w] << ' ' << len[w] << endl;
			pisz(w);
		}
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			dfs1(w);
			dp[v] += dp[w];
		}
	}
}

void dfs2(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = a + len[w] - 1;
			if(su[b] - su[a - 1] == 0) {
				wynik = max(wynik, dp[w] * h[w]);
				dfs2(w);
			}
			else {
				int c = ne[a];
				wynik = max(wynik, dp[w] * (h[v] + c - a));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> (s + n + 1);
		while(s[n + 1]) {
			n++;
			gd[n] = i;
		}
		n++;
		s[n] = 'z' + 1;
	}
	for(int i = 1; i <= m; ++i) cin >> cost[i];
	n++;
	s[n] = 'z' + 2;

	for(int i = 1; i <= n; ++i) {
		su[i] = su[i - 1];
		if(s[i] == 'z' + 1) su[i]++;
	}

	for(int i = n; i >= 1; --i) {
		ne[i] = ne[i + 1];
		if(s[i] == 'z' + 1) ne[i] = i;
	}
	int j = 1;
	int v = 1;
	par[v] = suf[v] = 1;

	for(int i = 1; i <= n; ++i) {
		while(j <= i) {
			int u = suf[par[v]];
			pair <int, int> r = fastscan(u, j + h[u], i - j - h[u]);
			u = r.first;
			if(!r.second) {
				suf[ov] = u;
				ov = 0;
			}

			int w = T[u][s[j + h[u]] - 'a'];
			if(w) {
				if(s[poz[w] + r.second] == s[i]) {
					v = u;
					break;
				}
				if(r.second) {
					gid++;
					par[gid] = u;
					par[w] = gid;
					h[gid] = h[u] + r.second;
					poz[gid] = poz[w];
					poz[w] += r.second;
					len[w] -= r.second;
					len[gid] = r.second;
					suf[ov] = gid;
					ov = gid;
					T[u][s[poz[gid]] - 'a'] = gid;
					T[gid][s[poz[w]] - 'a'] = w;
					r.first = gid;
				}
			}

			u = r.first;
			gid++;
			par[gid] = u;
			poz[gid] = j + h[u];
			h[gid] = n + 1 - j;
			len[gid] = h[gid] - h[u];
			T[u][s[poz[gid]] - 'a'] = gid;
			v = u;
			dp[gid] = cost[gd[j]];
			j++;
		}
	}

	dfs1(1);
	dfs2(1);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int A = 30;
const int N = 6e5;
char s[N + 7];
int poz[2 * N + 7];
int len[2 * N + 7];
int h[2 * N + 7];
int T[2 * N + 7][A];
int suf[2 * N + 7];
int gid = 1;
int ov;
int n;
int L;
long long dp[2 * N + 7];
int cost[N + 7];
int gd[N + 7];
int ssu[N + 7];
long long wynik = 0;

inline int ile(int a, int b) {
	return ssu[b] - ssu[a - 1];
}

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l == 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		if(T[v][i]) {
			dfs1(T[v][i]);
			dp[v] += dp[T[v][i]];
		}
	}
}

void dfs2(int v, int l) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = poz[w] + len[w] - 1;
			if(ile(a, b) == 0) {
				wynik = max(wynik, dp[w] * (l + len[w]));
				dfs2(w, l + len[w]);
			}
			else {
				int p = a;
				int k = b;
				b = a - 1;
				while(p <= k) {
					int s = (p + k) / 2;
					if(ile(a, s) == 0) {
						b = s;
						p = s + 1;
					}
					else k = s - 1;
				}
				wynik = max(wynik, dp[w] * (l + b - a + 1));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> (s + L + 1);
		while(s[L + 1]) {
			L++;
			gd[L] = i;
		}
		s[++L] = 'z' + 1;
		ssu[L] = 1;
	}
	for(int i = 1; i <= n; ++i) cin >> cost[i];
	s[++L] = 'z' + 2;
	int j = 1;
	int v = 1;
	suf[1] = 1;
	for(int i = 1; i <= L; ++i) ssu[i] += ssu[i - 1];

	for(int i = 1; i <= L; ++i) {
		ov = 0;
		while(j <= i) {
			pair <int, int> r = fastscan(v, j + h[v], i - j - h[v]);
			v = r.first;
			suf[ov] = v;
			int w = T[v][s[j + h[v]] - 'a'];
			int u = v;
			if(w && s[poz[w] + r.second] == s[i]) break;

			if(r.second) {
				++gid;
				len[gid] = r.second;
				len[w] -= r.second;
				h[gid] = h[v] + r.second;
				poz[gid] = poz[w];
				poz[w] += r.second;
				T[v][s[j + h[v]] - 'a'] = gid;
				T[gid][s[poz[w]] - 'a'] = w;
				v = gid;
				suf[ov] = gid;
				ov = gid;
			}

			++gid;
			h[gid] = L - j + 1;
			len[gid] = h[gid] - h[v];
			poz[gid] = i;
			T[v][s[j + h[v]] - 'a'] = gid;
			dp[gid] = cost[gd[j]];
			j++;
			v = suf[u];
		}
	}

	dfs1(1);
	dfs2(1, 0);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int A = 30;
const int N = 6e5;
char s[N + 7];
int poz[2 * N + 7];
int par[2 * N + 7];
int len[2 * N + 7];
int h[2 * N + 7];
int T[2 * N + 7][A];
int suf[2 * N + 7];
int gid = 1;
int ov;
int n;
int L;
long long dp[2 * N + 7];
int cost[N + 7];
int gd[N + 7];
int ssu[N + 7];
long long wynik = 0;

inline int ile(int a, int b) {
	return ssu[b] - ssu[a - 1];
}

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l == 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		if(T[v][i]) {
			dfs1(T[v][i]);
			dp[v] += dp[T[v][i]];
		}
	}
}

void dfs2(int v, int l) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = poz[w] + len[w] - 1;
			if(ile(a, b) == 0) {
				wynik = max(wynik, dp[w] * (l + len[w]));
				dfs2(w, l + len[w]);
			}
			else {
				int p = a;
				int k = b;
				b = a - 1;
				while(p <= k) {
					int s = (p + k) / 2;
					if(ile(a, s) == 0) {
						b = s;
						p = s + 1;
					}
					else k = s - 1;
				}
				wynik = max(wynik, dp[w] * (l + b - a + 1));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> (s + L + 1);
		while(s[L + 1]) {
			L++;
			gd[L] = i;
		}
		s[++L] = 'z' + 1;
		ssu[L] = 1;
	}
	for(int i = 1; i <= n; ++i) cin >> cost[i];
	s[++L] = 'z' + 2;
	int j = 1;
	int v = 1;
	par[1] = suf[1] = 1;
	for(int i = 1; i <= L; ++i) ssu[i] += ssu[i - 1];

	for(int i = 1; i <= L; ++i) {
		while(j <= i) {
			pair <int, int> r = fastscan(v, j + h[v], i - j - h[v]);
			v = r.first;
			suf[ov] = v;
			if(r.second == 0) ov = 0;
			int w = T[v][s[j + h[v]] - 'a'];
			if(w && s[poz[w] + r.second] == s[i]) break;

			if(r.second) {
				++gid;
				par[gid] = v;
				par[w] = gid;
				len[gid] = r.second;
				len[w] -= r.second;
				h[gid] = h[v] + r.second;
				poz[gid] = poz[w];
				poz[w] += r.second;
				T[v][s[j + h[v]] - 'a'] = gid;
				T[gid][s[poz[w]] - 'a'] = w;
				v = gid;
				suf[ov] = gid;
				ov = gid;
			}

			++gid;
			par[gid] = v;
			h[gid] = L - j + 1;
			len[gid] = h[gid] - h[v];
			poz[gid] = i;
			T[v][s[j + h[v]] - 'a'] = gid;
			dp[gid] = cost[gd[j]];
			j++;
			v = suf[par[v]];
		}
	}

	dfs1(1);
	dfs2(1, 0);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int N = 1e6 + 7;
const int A = 28;

int par[N];
int poz[N];
int len[N];
int suf[N];
int h[N];
int T[N][A];
char s[N];
int n, m;
int ov;
int gid = 1;

int gd[N];
int su[N];
int ne[N];
int cost[N];
long long dp[N];

long long wynik = 0;

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l <= 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void pisz(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			cout << v << ' ' << w << " - ";
			for(int j = poz[w]; j < poz[w] + len[w]; ++j) cout << s[j];
			cout << endl;
			pisz(w);
		}
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			dfs1(w);
			dp[v] += dp[w];
		}
	}
}

void dfs2(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = a + len[w] - 1;
			if(su[b] - su[a - 1] == 0) {
				//cout << "czysty " << v << ' ' << w << " -> " << dp[w] * h[w] << endl;
				wynik = max(wynik, dp[w] * h[w]);
				dfs2(w);
			}
			else {
				int c = ne[a];
				//cout << "nieczysty " << v << ' ' << w << " -> " << dp[w] * (h[v] + c - a) << endl;
				wynik = max(wynik, dp[w] * (h[v] + c - a));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> (s + n + 1);
		while(s[n + 1]) {
			n++;
			gd[n] = i;
		}
		n++;
		s[n] = 'z' + 1;
	}
	for(int i = 1; i <= m; ++i) cin >> cost[i];
	n++;
	s[n] = 'z' + 2;

	for(int i = 1; i <= n; ++i) {
		su[i] = su[i - 1];
		if(s[i] == 'z' + 1) su[i]++;
	}

	for(int i = n; i >= 1; --i) {
		ne[i] = ne[i + 1];
		if(s[i] == 'z' + 1) ne[i] = i;
	}
	int j = 1;
	int v = 1;
	par[v] = suf[v] = 1;

	//cout << "n = " << n << endl;
	//cout << (s + 1) << endl;
	//for(int i = 1; i <= n; ++i) cout << gd[i] << ' ';
	//cout << endl;

	for(int i = 1; i <= n; ++i) {
		while(j <= i) {
			//cout << "i j " << i << ' ' << j << endl;
			int u = suf[par[v]];
			if(!u) u = suf[par[par[v]]];
			//cout << "u = " << u << endl;
			pair <int, int> r = fastscan(u, j + h[u], i - j - h[u]);
			if(!r.second) {
				suf[ov] = r.first;
				ov = 0;
			}

			int w = T[u][s[j + h[u]] - 'a'];
			if(w) {
				if(s[poz[w] + r.second] == s[i]) break;
				if(r.second) {
					u = r.first;
					gid++;
					par[gid] = u;
					par[u] = gid;
					h[gid] = h[u] + r.second;
					poz[gid] = poz[w];
					poz[w] += r.second;
					len[w] -= r.second;
					len[gid] = r.second;
					suf[ov] = gid;
					ov = gid;
					T[u][s[poz[gid]] - 'a'] = gid;
					T[gid][s[poz[w]] - 'a'] = w;
					r.first = gid;
				}
			}

			u = r.first;
			gid++;
			par[gid] = u;
			poz[gid] = j + h[u];
			h[gid] = n + 1 - j;
			len[gid] = h[gid] - h[u];
			T[u][s[j + h[u]] - 'a'] = gid;
			v = gid;
			dp[gid] = cost[gd[j]];
			j++;
		}
	}

	dfs1(1);
	dfs2(1);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int N = 1300007;
const int A = 28;

int par[N];
int poz[N];
int len[N];
int suf[N];
int h[N];
int T[N][A];
char s[N];
int n, m;
int ov;
int gid = 1;

int gd[N];
int su[N];
int ne[N];
int cost[N];
long long dp[N];

long long wynik = 0;

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l <= 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void pisz(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			cout << v << ' ' << w << " - ";
			for(int j = poz[w]; j < poz[w] + len[w]; ++j) cout << s[j];
			cout << " - " << poz[w] << ' ' << len[w] << endl;
			pisz(w);
		}
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			dfs1(w);
			dp[v] += dp[w];
		}
	}
}

void dfs2(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = a + len[w] - 1;
			if(su[b] - su[a - 1] == 0) {
				wynik = max(wynik, dp[w] * h[w]);
				dfs2(w);
			}
			else {
				int c = ne[a];
				wynik = max(wynik, dp[w] * (h[v] + c - a));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> (s + n + 1);
		while(s[n + 1]) {
			n++;
			gd[n] = i;
		}
		n++;
		s[n] = 'z' + 1;
	}
	for(int i = 1; i <= m; ++i) cin >> cost[i];
	n++;
	s[n] = 'z' + 2;
	for(int i = 1; i <= n; ++i) {
		su[i] = su[i - 1];
		if(s[i] == 'z' + 1) su[i]++;
	}

	for(int i = n; i >= 1; --i) {
		ne[i] = ne[i + 1];
		if(s[i] == 'z' + 1) ne[i] = i;
	}
	int j = 1;
	int v = 1;
	par[v] = suf[v] = 1;

	for(int i = 1; i <= n; ++i) {
		while(j <= i) {
			int u = suf[par[v]];
			if(!u) u = suf[par[par[v]]];
			pair <int, int> r = fastscan(u, j + h[u], i - j - h[u]);
			u = r.first;
			if(!r.second) {
				suf[ov] = r.first;
				ov = 0;
			}

			int w = T[u][s[j + h[u]] - 'a'];
			if(w) {
				if(s[poz[w] + r.second] == s[i]) break;
				if(r.second) {
					gid++;
					par[gid] = u;
					par[w] = gid;
					h[gid] = h[u] + r.second;
					poz[gid] = poz[w];
					poz[w] += r.second;
					len[w] -= r.second;
					len[gid] = r.second;
					suf[ov] = gid;
					ov = gid;
					T[u][s[poz[gid]] - 'a'] = gid;
					T[gid][s[poz[w]] - 'a'] = w;
					r.first = gid;
				}
			}

			u = r.first;
			gid++;
			par[gid] = u;
			poz[gid] = j + h[u];
			h[gid] = n + 1 - j;
			len[gid] = h[gid] - h[u];
			T[u][s[poz[gid]] - 'a'] = gid;
			v = gid;
			dp[gid] = cost[gd[j]];
			j++;
		}
	}

	dfs1(1);
	dfs2(1);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int A = 30;
const int N = 6e5;
char s[N + 7];
int poz[2 * N + 7];
int len[2 * N + 7];
int h[2 * N + 7];
int T[2 * N + 7][A];
int suf[2 * N + 7];
int gid = 1;
int ov;
int n;
int L;
long long dp[2 * N + 7];
int cost[N + 7];
int gd[N + 7];
int ssu[N + 7];
long long wynik = 0;

inline int ile(int a, int b) {
	return ssu[b] - ssu[a - 1];
}

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l == 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		if(T[v][i]) {
			dfs1(T[v][i]);
			dp[v] += dp[T[v][i]];
		}
	}
}

void dfs2(int v, int l) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = poz[w] + len[w] - 1;
			if(ile(a, b) == 0) {
				wynik = max(wynik, dp[w] * (l + len[w]));
				dfs2(w, l + len[w]);
			}
			else {
				int p = a;
				int k = b;
				b = a - 1;
				while(p <= k) {
					int s = (p + k) / 2;
					if(ile(a, s) == 0) {
						b = s;
						p = s + 1;
					}
					else k = s - 1;
				}
				wynik = max(wynik, dp[w] * (l + b - a + 1));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> (s + L + 1);
		while(s[L + 1]) {
			L++;
			gd[L] = i;
		}
		s[++L] = 'z' + 1;
		ssu[L] = 1;
	}
	for(int i = 1; i <= n; ++i) cin >> cost[i];
	s[++L] = 'z' + 2;
	int j = 1;
	int v = 1;
	suf[1] = 1;
	for(int i = 1; i <= L; ++i) ssu[i] += ssu[i - 1];

	for(int i = 1; i <= L; ++i) {
		while(j <= i) {
			pair <int, int> r = fastscan(v, j + h[v], i - j - h[v]);
			v = r.first;
			int u = v;
			suf[ov] = v;
			if(r.second == 0) ov = 0;
			int w = T[v][s[j + h[v]] - 'a'];
			if(w && s[poz[w] + r.second] == s[i]) break;

			if(r.second) {
				++gid;
				len[gid] = r.second;
				len[w] -= r.second;
				h[gid] = h[v] + r.second;
				poz[gid] = poz[w];
				poz[w] += r.second;
				T[v][s[j + h[v]] - 'a'] = gid;
				T[gid][s[poz[w]] - 'a'] = w;
				v = gid;
				suf[ov] = gid;
				ov = gid;
			}

			++gid;
			h[gid] = L - j + 1;
			len[gid] = h[gid] - h[v];
			poz[gid] = i;
			T[v][s[j + h[v]] - 'a'] = gid;
			dp[gid] = cost[gd[j]];
			j++;
			v = suf[u];
		}
	}

	dfs1(1);
	dfs2(1, 0);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int N = 1300007;
const int A = 28;

int par[N];
int poz[N];
int len[N];
int suf[N];
int h[N];
int T[N][A];
char s[N];
int n, m;
int ov;
int gid = 1;

int gd[N];
int su[N];
int ne[N];
int cost[N];
long long dp[N];

long long wynik = 0;

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l <= 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void pisz(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			cout << v << ' ' << w << " - ";
			for(int j = poz[w]; j < poz[w] + len[w]; ++j) cout << s[j];
			cout << " - " << poz[w] << ' ' << len[w] << endl;
			pisz(w);
		}
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			dfs1(w);
			dp[v] += dp[w];
		}
	}
}

void dfs2(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = a + len[w] - 1;
			if(su[b] - su[a - 1] == 0) {
				wynik = max(wynik, dp[w] * h[w]);
				dfs2(w);
			}
			else {
				int c = ne[a];
				wynik = max(wynik, dp[w] * (h[v] + c - a));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> (s + n + 1);
		while(s[n + 1]) {
			n++;
			gd[n] = i;
		}
		n++;
		s[n] = 'z' + 1;
	}
	for(int i = 1; i <= m; ++i) cin >> cost[i];
	n++;
	s[n] = 'z' + 2;

	for(int i = 1; i <= n; ++i) {
		su[i] = su[i - 1];
		if(s[i] == 'z' + 1) su[i]++;
	}

	for(int i = n; i >= 1; --i) {
		ne[i] = ne[i + 1];
		if(s[i] == 'z' + 1) ne[i] = i;
	}
	int j = 1;
	int v = 1;
	par[v] = suf[v] = 1;

	for(int i = 1; i <= n; ++i) {
		while(j <= i) {
			int u = v;
			pair <int, int> r = fastscan(u, j + h[u], i - j - h[u]);
			u = r.first;
			if(!r.second) {
				suf[ov] = u;
				ov = 0;
			}

			int w = T[u][s[j + h[u]] - 'a'];
			if(w) {
				if(s[poz[w] + r.second] == s[i]) {
					v = u;
					break;
				}
				if(r.second) {
					gid++;
					par[gid] = u;
					par[w] = gid;
					h[gid] = h[u] + r.second;
					poz[gid] = poz[w];
					poz[w] += r.second;
					len[w] -= r.second;
					len[gid] = r.second;
					suf[ov] = gid;
					ov = gid;
					T[u][s[poz[gid]] - 'a'] = gid;
					T[gid][s[poz[w]] - 'a'] = w;
					r.first = gid;
				}
			}

			u = r.first;
			gid++;
			par[gid] = u;
			poz[gid] = j + h[u];
			h[gid] = n + 1 - j;
			len[gid] = h[gid] - h[u];
			T[u][s[poz[gid]] - 'a'] = gid;
			v = suf[par[u]];
			dp[gid] = cost[gd[j]];
			j++;
		}
	}

	dfs1(1);
	dfs2(1);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int A = 30;
const int N = 6e5;
char s[N + 7];
int poz[2 * N + 7];
int par[2 * N + 7];
int len[2 * N + 7];
int h[2 * N + 7];
int T[2 * N + 7][A];
int suf[2 * N + 7];
int gid = 1;
int ov;
int n;
int L;
long long dp[2 * N + 7];
int cost[N + 7];
int gd[N + 7];
int ssu[N + 7];
long long wynik = 0;

inline int ile(int a, int b) {
	return ssu[b] - ssu[a - 1];
}

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l == 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		if(T[v][i]) {
			dfs1(T[v][i]);
			dp[v] += dp[T[v][i]];
		}
	}
}

void dfs2(int v, int l) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = poz[w] + len[w] - 1;
			if(ile(a, b) == 0) {
				wynik = max(wynik, dp[w] * (l + len[w]));
				dfs2(w, l + len[w]);
			}
			else {
				int p = a;
				int k = b;
				b = a - 1;
				while(p <= k) {
					int s = (p + k) / 2;
					if(ile(a, s) == 0) {
						b = s;
						p = s + 1;
					}
					else k = s - 1;
				}
				wynik = max(wynik, dp[w] * (l + b - a + 1));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> (s + L + 1);
		while(s[L + 1]) {
			L++;
			gd[L] = i;
		}
		s[++L] = 'z' + 1;
		ssu[L] = 1;
	}
	for(int i = 1; i <= n; ++i) cin >> cost[i];
	s[++L] = 'z' + 2;
	int j = 1;
	int v = 1;
	par[1] = suf[1] = 1;
	for(int i = 1; i <= L; ++i) ssu[i] += ssu[i - 1];

	for(int i = 1; i <= L; ++i) {
		ov = 0;
		while(j <= i) {
			pair <int, int> r = fastscan(v, j + h[v], i - j - h[v]);
			v = r.first;
			suf[ov] = v;
			int w = T[v][s[j + h[v]] - 'a'];
			int u = par[v];
			if(w && s[poz[w] + r.second] == s[i]) break;

			if(r.second) {
				++gid;
				par[gid] = v;
				par[w] = gid;
				len[gid] = r.second;
				len[w] -= r.second;
				h[gid] = h[v] + r.second;
				poz[gid] = poz[w];
				poz[w] += r.second;
				T[v][s[j + h[v]] - 'a'] = gid;
				T[gid][s[poz[w]] - 'a'] = w;
				v = gid;
				suf[ov] = gid;
				ov = gid;
			}

			++gid;
			par[gid] = v;
			h[gid] = L - j + 1;
			len[gid] = h[gid] - h[v];
			poz[gid] = i;
			T[v][s[j + h[v]] - 'a'] = gid;
			dp[gid] = cost[gd[j]];
			j++;
			v = suf[u];
		}
	}

	dfs1(1);
	dfs2(1, 0);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int N = 1300007;
const int A = 28;

int par[N];
int poz[N];
int len[N];
int suf[N];
int h[N];
int T[N][A];
char s[N];
int n, m;
int ov;
int gid = 1;

int gd[N];
int su[N];
int ne[N];
int cost[N];
long long dp[N];

long long wynik = 0;

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		//cout << "v";
		//cout << "v = " << v << endl;
		if(l <= 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void pisz(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			cout << v << ' ' << w << " - ";
			for(int j = poz[w]; j < poz[w] + len[w]; ++j) cout << s[j];
			cout << " - " << poz[w] << ' ' << len[w] << endl;
			pisz(w);
		}
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			dfs1(w);
			dp[v] += dp[w];
		}
	}
}

void dfs2(int v) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = a + len[w] - 1;
			if(su[b] - su[a - 1] == 0) {
				wynik = max(wynik, dp[w] * h[w]);
				dfs2(w);
			}
			else {
				int c = ne[a];
				wynik = max(wynik, dp[w] * (h[v] + c - a));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> (s + n + 1);
		while(s[n + 1]) {
			n++;
			gd[n] = i;
		}
		n++;
		s[n] = 'z' + 1;
	}
	for(int i = 1; i <= m; ++i) cin >> cost[i];
	n++;
	s[n] = 'z' + 2;

	for(int i = 1; i <= n; ++i) {
		su[i] = su[i - 1];
		if(s[i] == 'z' + 1) su[i]++;
	}

	for(int i = n; i >= 1; --i) {
		ne[i] = ne[i + 1];
		if(s[i] == 'z' + 1) ne[i] = i;
	}
	int j = 1;
	int v = 1;
	par[v] = suf[v] = 1;

	for(int i = 1; i <= n; ++i) {
		while(j <= i) {
			int u = suf[par[par[v]]];
			//cout << "fstcan" << endl;
			pair <int, int> r = fastscan(u, j + h[u], i - j - h[u]);
			//cout << endl;
			u = r.first;
			if(!r.second) {
				suf[ov] = u;
				ov = 0;
			}

			int w = T[u][s[j + h[u]] - 'a'];
			if(w) {
				if(s[poz[w] + r.second] == s[i]) {
					v = u;
					break;
				}
				if(r.second) {
					gid++;
					par[gid] = u;
					par[w] = gid;
					h[gid] = h[u] + r.second;
					poz[gid] = poz[w];
					poz[w] += r.second;
					len[w] -= r.second;
					len[gid] = r.second;
					suf[ov] = gid;
					ov = gid;
					T[u][s[poz[gid]] - 'a'] = gid;
					T[gid][s[poz[w]] - 'a'] = w;
					r.first = gid;
				}
			}

			u = r.first;
			gid++;
			par[gid] = u;
			poz[gid] = j + h[u];
			h[gid] = n + 1 - j;
			len[gid] = h[gid] - h[u];
			T[u][s[poz[gid]] - 'a'] = gid;
			v = gid;
			dp[gid] = cost[gd[j]];
			j++;
		}
	}

	dfs1(1);
	dfs2(1);
	//pisz(1);
	cout << wynik << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int A = 30;
const int N = 6e5;
char s[N + 7];
int poz[2 * N + 7];
int par[2 * N + 7];
int len[2 * N + 7];
int h[2 * N + 7];
int T[2 * N + 7][A];
int suf[2 * N + 7];
int gid = 1;
int ov;
int n;
int L;
long long dp[2 * N + 7];
int cost[N + 7];
int gd[N + 7];
int ssu[N + 7];
long long wynik = 0;

inline int ile(int a, int b) {
	return ssu[b] - ssu[a - 1];
}

pair <int, int> fastscan(int v, int a, int l) {
	while(1) {
		if(l == 0) return {v, 0};
		int w = T[v][s[a] - 'a'];
		if(l < len[w]) return {v, l};
		l -= len[w];
		a += len[w];
		v = w;
	}
}

void dfs1(int v) {
	for(int i = 0; i < A; ++i) {
		if(T[v][i]) {
			dfs1(T[v][i]);
			dp[v] += dp[T[v][i]];
		}
	}
}

void dfs2(int v, int l) {
	for(int i = 0; i < A; ++i) {
		int w = T[v][i];
		if(w) {
			int a = poz[w];
			int b = poz[w] + len[w] - 1;
			if(ile(a, b) == 0) {
				wynik = max(wynik, dp[w] * (l + len[w]));
				dfs2(w, l + len[w]);
			}
			else {
				int p = a;
				int k = b;
				b = a - 1;
				while(p <= k) {
					int s = (p + k) / 2;
					if(ile(a, s) == 0) {
						b = s;
						p = s + 1;
					}
					else k = s - 1;
				}
				wynik = max(wynik, dp[w] * (l + b - a + 1));
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> (s + L + 1);
		while(s[L + 1]) {
			L++;
			gd[L] = i;
		}
		s[++L] = 'z' + 1;
		ssu[L] = 1;
	}
	for(int i = 1; i <= n; ++i) cin >> cost[i];
	s[++L] = 'z' + 2;
	int j = 1;
	int v = 1;
	par[1] = suf[1] = 1;
	for(int i = 1; i <= L; ++i) ssu[i] += ssu[i - 1];

	for(int i = 1; i <= L; ++i) {
		while(j <= i) {
			pair <int, int> r = fastscan(v, j + h[v], i - j - h[v]);
			v = r.first;
			int u = v;
			suf[ov] = v;
			if(r.second == 0) ov = 0;
			int w = T[v][s[j + h[v]] - 'a'];
			if(w && s[poz[w] + r.second] == s[i]) break;

			if(r.second) {
				++gid;
				par[gid] = v;
				par[w] = gid;
				len[gid] = r.second;
				len[w] -= r.second;
				h[gid] = h[v] + r.second;
				poz[gid] = poz[w];
				poz[w] += r.second;
				T[v][s[j + h[v]] - 'a'] = gid;
				T[gid][s[poz[w]] - 'a'] = w;
				v = gid;
				suf[ov] = gid;
				ov = gid;
			}

			++gid;
			par[gid] = v;
			h[gid] = L - j + 1;
			len[gid] = h[gid] - h[v];
			poz[gid] = i;
			T[v][s[j + h[v]] - 'a'] = gid;
			dp[gid] = cost[gd[j]];
			j++;
			v = suf[u];
		}
	}

	dfs1(1);
	dfs2(1, 0);
	cout << wynik << endl;
	return 0;
}