CodeForces

You are given n strings ti. Each string has cost ci.

Let's define the function of string , where ps, i is the number of occurrences of s in ti, |s| is the length of the string s. Find the maximal value of function f(s) over all strings.

Note that the string s is not necessarily some string from t.


Input

The first line contains the only integer n (1 ≤ n ≤ 105) — the number of strings in t.

Each of the next n lines contains contains a non-empty string ti. ti contains only lowercase English letters.

It is guaranteed that the sum of lengths of all strings in t is not greater than 5·105.

The last line contains n integers ci ( - 107 ≤ ci ≤ 107) — the cost of the i-th string.

Output

Print the only integer a — the maximal value of the function f(s) over all strings s. Note one more time that the string s is not necessarily from t.

Examples
Input
2
aa
bb
2 1
Output
4
Input
2
aa
ab
2 1
Output
5
#include<bits/stdc++.h>
#define ll long long
#define rep2(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
char c[maxn],s[maxn]; int End[maxn];
struct SAM{
    int ch[maxn][26],fa[maxn],maxlen[maxn],cnt,last;
    int a[maxn],b[maxn],num[maxn]; ll val[maxn],ans=0;
    void init()
    {
        cnt=1; memset(ch[1],0,sizeof(ch[1]));
    }
    int add(int x)
    {
       int np=++cnt,p=last; last=np;
       maxlen[np]=maxlen[p]+1;memset(ch[np],0,sizeof(ch[np]));
       while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
       if(!p) fa[np]=1;
       else {
         int q=ch[p][x];
         if(maxlen[q]==maxlen[p]+1) fa[np]=q;
         else {
            int nq=++cnt; maxlen[nq]=maxlen[p]+1;
            fa[nq]=fa[q]; fa[q]=fa[np]=nq;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
         }
       }
    }
   void sort()
   {
     rep(i,1,cnt) a[i]=0;
     rep(i,1,cnt) a[maxlen[i]]++;
     rep(i,1,cnt) a[i]+=a[i-1];
     rep(i,1,cnt) b[a[maxlen[i]]--]=i;
   }
   void solve(int N)
   {
      sort();
      rep(i,1,N) scanf("%d",&num[i]);
      rep(i,1,N){
          int now=1;
          rep(j,End[i-1]+1,End[i]){
              now=ch[now][s[j]-'a'];
              val[now]+=num[i];
          }
      }
      rep2(i,cnt,1) val[fa[b[i]]]+=val[b[i]];
      rep(i,1,cnt) ans=max(ans,val[i]*maxlen[i]);
   }
}T;
int a[maxn];
int main()
{
    int N,L;
    scanf("%d",&N);
    T.init();
    rep(i,1,N) {
        scanf("%s",c+1);
        L=strlen(c+1); T.last=1;
        rep(j,1,L) T.add(c[j]-'a');
        rep(j,1,L) s[End[i-1]+j]=c[j];
        End[i]=End[i-1]+L;
    }
    T.solve(N);
    printf("%lld
",T.ans);
    return 0;
}

N个串,给个串有一个价值num[i],现在让你找一个串X,它在第i个字符串出现次数为pi,而且∑len(X)*num[i]*p[i]最大。

思路:后缀自动机,对于每个集合,num之和一样,所以肯定选择最长的一个。

原文地址:https://www.cnblogs.com/hua-dong/p/10427544.html