看到就知道咋作了吧。。。node
在parent樹上的LCA處統計答案就行了,由於兩個子串的lcs(後綴的lcp)在parent樹上位置是在LCA處,因此對於每一個點找一下來自不一樣子樹(使LCA等於它)更新答案,而後取後綴max(和)ios
這裏從後往前插入會比較方便git
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define ll long long const ll inf = 9223372036854775803; int read(){ int x=0,pos=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0; for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return pos?x:-x; } const int N = 1000201; ll a[N],b[N],mx[N],ans[N],tms[N],mi[N]; ll ti[N],lnk[N],sz[N]; char s[N]; int n; struct tree{ int ch[26],fa,len; }t[N]; int las=1,tot=1; void insert(int c,int id){ int p=las,np=las=++tot; t[np].len=t[p].len+1;sz[np]=1;mx[np]=mi[np]=a[id]; for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np; if(!p) t[np].fa=1; else{ int q=t[p].ch[c]; if(t[p].len+1==t[q].len) t[np].fa=q; else{ int nq=++tot; t[nq]=t[q];t[nq].len=t[p].len+1; t[np].fa=t[q].fa=nq; for(;t[p].ch[c]==q;p=t[p].fa) t[p].ch[c]=nq; } } } struct node{ int v,nex; }edge[N<<1]; int head[N],top=0; void add(int u,int v){ edge[++top].v=v; edge[top].nex=head[u]; head[u]=top; } void dfs(int now){ for(int i=head[now];i;i=edge[i].nex){ int v=edge[i].v; dfs(v);tms[t[now].len]+=sz[now]*sz[v]; sz[now]+=sz[v]; if(mx[now]!=-inf) ans[t[now].len]=max(ans[t[now].len],mx[now]*mx[v]); if(mi[now]!=inf) ans[t[now].len]=max(ans[t[now].len],mi[now]*mi[v]); mx[now]=max(mx[now],mx[v]);mi[now]=min(mi[now],mi[v]); } } int main(){ //freopen("1.in","r",stdin); //freopen("1.txt","w",stdout); n=read(); scanf("%s",s+1); for(int i=1;i<=n;i++){ a[i]=read(); } for(int i=1;i<N;i++){ mx[i]=-inf;mi[i]=inf,ans[i]=-inf; } for(int i=n;i>=1;i--){ insert(s[i]-'a',i); } for(int i=1;i<=tot;i++) add(t[i].fa,i); dfs(1); for(int i=n-1;i>=1;i--) tms[i-1]+=tms[i],ans[i-1]=max(ans[i-1],ans[i]); for(int i=0;i<=n-1;i++){ printf("%lld %lld\n",tms[i],(ans[i]==-inf)?0:ans[i]); } return 0; }