其实没有想象中难, 我们知道, 两个串的最长公共后缀就是 parent 树上的LCA 的len
对于出现次数, 枚举每一个 LCA, 然后 siz 乘一下
因为如果 len 出现了, len - 1 也出现了, 所以求一个后缀和
对于最大值, 我们维护子树最大与次大, 因为有负数, 所以还要维护次小与最小
同样对最大值也求一个后缀最大
#include<bits/stdc++.h>
#define N 600050
using namespace std;
typedef long long ll;
const ll inf = 900000000000000000;
int n; char s[N]; ll a[N];
struct Node{
int ch[26], link, len, siz;
} t[N];
ll mx1[N], mx2[N], mi1[N], mi2[N];
ll sum[N], ans[N];
int last, tot;
void Extend(int Id, int c){
int cur = ++tot, p = last;
mx1[cur] = a[Id]; mx2[cur] = -inf; mi1[cur] = a[Id]; mi2[cur] = inf;
t[cur].len = t[p].len + 1; t[cur].siz = 1;
for(;p && !t[p].ch[c]; p = t[p].link) t[p].ch[c] = cur;
if(!p) t[cur].link = 1;
else{
int q = t[p].ch[c];
if(t[q].len == t[p].len + 1) t[cur].link = q;
else{
int clone = ++tot;
mx1[clone] = mx2[clone] = -inf; mi1[clone] = mi2[clone] = inf;
t[clone].link = t[q].link;
t[clone].len = t[p].len + 1;
for(int i=0; i<26; i++) t[clone].ch[i] = t[q].ch[i];
for(;p && t[p].ch[c] == q; p = t[p].link) t[p].ch[c] = clone;
t[cur].link = t[q].link = clone;
}
} last = cur;
}
vector<int> v[N];
void mxUpt(ll w, int u){ if(w > mx1[u]) mx2[u] = mx1[u], mx1[u] = w; else if(w > mx2[u]) mx2[u] = w;}
void miUpt(ll w, int u){ if(w < mi1[u]) mi2[u] = mi1[u], mi1[u] = w; else if(w < mi2[u]) mi2[u] = w;}
void dfs(int u){
for(int i=0; i<v[u].size(); i++){
int son = v[u][i]; dfs(son);
sum[t[u].len] += 1ll * t[u].siz * t[son].siz;
t[u].siz += t[son].siz;
mxUpt(mx1[son], u); mxUpt(mx2[son], u);
miUpt(mi1[son], u); miUpt(mi2[son], u);
} if(t[u].siz < 2) return;
if(mx2[u] != -inf && mi2[u] != inf)
ans[t[u].len] = max(ans[t[u].len], max(mx1[u] * mx2[u], mi1[u] * mi2[u]));
}
int main(){
scanf("%d%s", &n, s+1); last = tot = 1; mx1[1] = mx2[1] = -inf; mi1[1] = mi2[1] = inf;
for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
for(int i=n; i>=1; i--) Extend(i, s[i] - 'a');
for(int i=2; i<=tot; i++) v[t[i].link].push_back(i);
for(int i=1; i<=tot; i++) ans[i] = -inf;
dfs(1);
for(int i=n-1; i>=0; i--) ans[i] = max(ans[i], ans[i+1]), sum[i] += sum[i+1];
for(int i=0; i<n; i++){
printf("%lld %lld\n", sum[i], sum[i] ? ans[i] : 0);
} return 0;
}