用常用的套路,排序之后从大到小插入height,用并查集维护即可。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int maxn=300010; const ll inf=1e18; int n,sa[maxn],H[maxn],ra[maxn],tong[maxn],m,tp[maxn],fa[maxn]; ll ans1[maxn],ans2[maxn],c[maxn]; char s[maxn]; int getfa(int x){return (x==fa[x])?x:fa[x]=getfa(fa[x]);} void rsort(){ for(int i=0;i<=m;++i)tong[i]=0; for(int i=1;i<=n;++i)tong[ra[tp[i]]]++; for(int i=1;i<=m;++i)tong[i]+=tong[i-1]; for(int i=n;i>=1;--i)sa[tong[ra[tp[i]]]--]=tp[i]; } int cmp(int x,int y,int w){return tp[x]==tp[y]&&tp[x+w]==tp[y+w];} void pre(){ for(int i=1;i<=n;++i)ra[i]=s[i]-'a'+1,tp[i]=i; m=32;rsort(); for(int w=1,p=1,i;p<n;w+=w,m=p){ for(p=0,i=n-w+1;i<=n;++i)tp[++p]=i; for(i=1;i<=n;++i)if(sa[i]>w)tp[++p]=sa[i]-w; rsort();swap(tp,ra);ra[sa[1]]=p=1; for(i=2;i<=n;++i)ra[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p; } int j,k=0; for(int i=1;i<=n;H[ra[i++]]=k) for(k=k?k-1:k,j=sa[ra[i]-1];s[i+k]==s[j+k];++k); } struct node{ int id,v; bool operator<(const node&t)const{ return v<t.v; } }tmp[maxn]; struct lian{ int l,r; ll ma,mi,len; }a[maxn]; void merge(int x,int y,int w){ x=getfa(x);y=getfa(y); ll t1=max(a[x].ma*a[y].ma,a[x].mi*a[y].mi); ll t2=max(a[x].ma*a[y].mi,a[x].mi*a[y].ma); ll t3=min(a[x].ma*a[y].ma,a[x].mi*a[y].mi); ll t4=min(a[x].ma*a[y].mi,a[x].mi*a[y].ma); a[x].ma=max(a[x].ma,a[y].ma); a[x].mi=min(a[y].mi,a[x].mi); ans1[w]+=a[x].len*a[y].len; a[x].len+=a[y].len; fa[y]=x; ans2[w]=max(ans2[w],max(t1,t2)); } int main(){ cin>>n; scanf("%s",s+1); pre(); for(int i=1;i<=n;++i){ tmp[i-1].id=i,tmp[i-1].v=H[i]; } sort(tmp+1,tmp+n); for(int i=1;i<=n;++i)scanf("%lld",&c[i]); for(int i=1;i<=n;++i){ a[i].mi=a[i].ma=c[sa[i]]; a[i].l=a[i].r=i;a[i].len=1; fa[i]=i; } //for(int i=1;i<=n;++i)cout<<sa[i]<<' '<<H[i]<<endl; for(int i=0;i<=n;++i)ans2[i]=-inf; for(int i=n-1;i>=1;--i){ merge(tmp[i].id-1,tmp[i].id,tmp[i].v); } for(int i=n-2;i>=0;--i){ ans1[i]+=ans1[i+1]; ans2[i]=max(ans2[i],ans2[i+1]); } for(int i=0;i<=n-1;++i){ printf("%lld ",ans1[i]); if(ans2[i]==-inf)printf("%lld ",0); else printf("%lld ",ans2[i]); } return 0; }