题目:BZOJ4199.
题目大意:给定一个字符串
S
S
S,并给出一个长度为
∣
S
∣
|S|
∣S∣的序列
a
i
a_i
ai.现在设
S
i
S_i
Si表示
S
S
S以第
i
i
i个字符开始的后缀,对于每个
0
≤
r
<
∣
S
∣
0\leq r<|S|
0≤r<∣S∣要求
i
=
̸
j
i=\not{}j
i≠j使得
S
i
,
S
j
S_i,S_j
Si,Sj的最长公共前缀LCP至少为
r
r
r的方案数和
a
i
∗
a
j
a_i*a_j
ai∗aj最大的方案.
1
≤
∣
S
∣
≤
3
∗
1
0
5
,
∣
a
i
∣
≤
1
0
9
1\leq |S|\leq 3*10^5,|a_i|\leq 10^9
1≤∣S∣≤3∗105,∣ai∣≤109.
做这道题之前建议先去做做BZOJ3238差异.
首先可以转化为求每个LCP恰好为 r r r的数量和最大值,最后后缀和,后缀最大值处理一下即可.
先考虑如何求数量.考虑两个串的LCP恰好为 r r r在后缀树上等价于两个点的LCA深度为 r r r,那么用直接在后缀树上树形DP即可.
然后考虑 a i a_i ai和 a j a_j aj相乘的最大值.这个其实也不难,给每个表示后缀结尾的节点附上一个点权为它对应的 a i a_i ai,也树形DP处理一遍就好了,不过注意需要有负数的情况,记一下最大值最小值就好了.
时间复杂度 O ( ∣ S ∣ Σ ) O(|S|\Sigma) O(∣S∣Σ).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=300000,C=26,inf=(1<<30)-1;
const LL INF=(1LL<<61)-1;
int n;
LL a[N+9],cnt[N+9],ans[N+9];
char s[N+9];
struct automaton{
int s[C],len,par;
}tr[N*2+9];
int cn,last,rght[N*2+9],mx[N*2+9],mn[N*2+9];
void Build_sam(){cn=last=1;}
void extend(int x){
int np=++cn,p=last;
tr[np].len=tr[p].len+1;rght[np]=1;mn[np]=mx[np]=a[n-tr[np].len+1];
last=np;
while (p&&!tr[p].s[x]) tr[p].s[x]=np,p=tr[p].par;
if (!p) tr[np].par=1;
else{
int q=tr[p].s[x];
if (tr[p].len+1==tr[q].len) tr[np].par=q;
else{
tr[++cn]=tr[q];tr[cn].len=tr[p].len+1;mx[cn]=-inf,mn[cn]=inf;
tr[np].par=tr[q].par=cn;
while (p&&tr[p].s[x]==q) tr[p].s[x]=cn,p=tr[p].par;
}
}
}
struct side{
int y,next;
}e[N*2+9];
int lin[N*2+9],top;
void ins(int x,int y){
e[++top].y=y;
e[top].next=lin[x];
lin[x]=top;
}
void Build_parent(){
for (int i=2;i<=cn;++i)
ins(tr[i].par,i);
}
LL trc[N*2+9],tra[N*2+9];
void dfs(int k){
tra[k]=-INF;
for (int i=lin[k];i;i=e[i].next){
dfs(e[i].y);
trc[k]+=(LL)rght[k]*rght[e[i].y];
if (!rght[e[i].y]) continue;
if (rght[k])
tra[k]=max(max(max((LL)mx[k]*mx[e[i].y],(LL)mn[k]*mn[e[i].y]),
max((LL)mx[k]*mn[e[i].y],(LL)mn[k]*mx[e[i].y])),tra[k]);
rght[k]+=rght[e[i].y];
mx[k]=max(mx[k],mx[e[i].y]);
mn[k]=min(mn[k],mn[e[i].y]);
}
}
Abigail into(){
scanf("%d",&n);
scanf("%s",s+1);
for (int i=1;i<=n;++i)
scanf("%lld",&a[i]);
}
Abigail work(){
Build_sam();
for (int i=n;i>=1;--i)
extend(s[i]-'a');
Build_parent();
dfs(1);
for (int i=0;i<=n;++i) ans[i]=-INF;
for (int i=1;i<=cn;++i)
cnt[tr[i].len]+=trc[i],ans[tr[i].len]=max(ans[tr[i].len],tra[i]);
for (int i=n-1;i>=0;--i)
cnt[i]+=cnt[i+1],ans[i]=max(ans[i],ans[i+1]);
}
Abigail outo(){
for (int i=0;i<n;++i)
printf("%lld %lld\n",cnt[i],ans[i]==-INF?0:ans[i]);
}
int main(){
into();
work();
outo();
return 0;
}