原题
题目大意
给你
n≤105
个字符串,字符串总长度
≤5∗105
,每个字符串有一个价值
ci
,让你构造一个字符串,使得
∑ni=1ci∗ps,i∗|s|
最大,
s
为构造的字符串,
解题思路
把字符串全部拼在一起,两两之间插入一个没有出现过的字符,然后做后缀数组。对于连续的一段
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 600005
#define ll long long
using namespace std;
int s[maxn],sa[maxn],rank[maxn],wss[maxn],wv[maxn],x[maxn],y[maxn];
int cost[maxn],l[maxn],r[maxn],height[maxn],thlen[maxn],belong[maxn];
ll sum[maxn],ans;
int n,len;
char ch[maxn];
int nowlen;
int st[maxn];
void Read(){
nowlen=0;
char c=getchar();
while (c<'a' || c>'z') c=getchar();
while (c>='a' && c<='z') {
ch[++nowlen]=c;
c=getchar();
}
}
void get_height() {
fo(i,1,len) rank[sa[i]]=i;
int k=0,j;
for(int i=1;i<=len;height[rank[i++]]=k)
for(k ? k-- : k,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);
}
bool compare(int *rank,int i,int j,int k){
return rank[i]==rank[j] && rank[i+k]==rank[j+k];
}
void SA() {
int i,j,p,m='z'+n+1;
fo(i,1,len) wss[x[i]=s[i]]++;
fo(i,1,m) wss[i]+=wss[i-1];
fo(i,1,len) sa[wss[x[i]]--]=i;
for(j=1,p=0;p<len;m=p,j*=2) {
for(p=0,i=len-j+1;i<=len;i++) y[++p]=i;
for(i=1;i<=len;i++) if (sa[i]>j) y[++p]=sa[i]-j;
for(i=1;i<=len;i++) wv[i]=x[y[i]];
for(i=1;i<=m;i++) wss[i]=0;
for(i=1;i<=len;i++) wss[wv[i]]++;
for(i=1;i<=m;i++) wss[i]+=wss[i-1];
for(i=len;i>=1;i--) sa[wss[wv[i]]--]=y[i];
swap(x,y);
for(x[sa[1]]=1,p=1,i=2;i<=len;i++)
x[sa[i]]=compare(y,sa[i-1],sa[i],j) ? p : ++p;
}
}
int main(){
scanf("%d",&n);
fo(i,1,n) {
Read();
int tmp=nowlen;
fo(j,1,nowlen) {
s[++len]=ch[j]-'a'+1;
thlen[len]=tmp;
tmp--;
belong[len]=i;
}
s[++len]=i+'z';
thlen[len]=0;
belong[len]=n+1;
}
fo(i,1,n) scanf("%d",&cost[i]);
SA();
get_height();
fo(i,1,len) sum[i]=sum[i-1]+cost[belong[sa[i]]];
fo(i,1,len) {
int tmp1,tmp2;
if (i==1) tmp1=0; else tmp1=height[i];
if (i==n) tmp2=0; else tmp2=height[i+1];
if (thlen[sa[i]]>max(tmp1,tmp2))
ans=max(ans,1ll*cost[belong[sa[i]]]*thlen[sa[i]]);
}
st[0]=0;
fo(i,1,len) {
while (st[0]>0 && height[st[st[0]]]>=height[i]) st[0]--;
if (st[0]==0) l[i]=1; else l[i]=st[st[0]];
st[++st[0]]=i;
}
st[0]=0;
fd(i,len,1) {
while (st[0]>0 && height[st[st[0]]]>=height[i]) st[0]--;
if (st[0]==0) r[i]=len; else r[i]=st[st[0]];
st[++st[0]]=i;
ll now=sum[r[i]-1]-sum[l[i]-1];
ans=max(ans,now*height[i]);
}
printf("%I64d",ans);
return 0;
}