CodeForces - 616F:Expensive Strings (后缀自动机)
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.
OutputPrint 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.
Examples2
aa
bb
2 1
4
2
aa
ab
2 1
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\n",T.ans); return 0; }
N个串,给个串有一个价值num[i],现在让你找一个串X,它在第i个字符串出现次数为pi,而且∑len(X)*num[i]*p[i]最大。
思路:后缀自动机,对于每个集合,num之和一样,所以肯定选择最长的一个。