给出一个 长度为 n 的字符串,每一位有一个权值 val。定义两个位字符为 r 相似,是指分别从这两个字符开始,到后面的 r 个字符都相等。两个 r 相似的字符还有一个权值为这两个字符权值的乘积。问对于 r = 0, 1, 2, … , n - 1,统计出有多少种方法可以选出 2 个“r 相似”的字符,并回答选择 2 个”r 相似”的字符可以得到的权值的最大值。
首先说一个暴力的做法,可以得到 50 分:
先预处理出 1 - n 累加的结果。对于这个字符串求出 Height 数组,然后枚举 r ,按 r 把 Height 分组,然后统计方案数:假设组内有 x 个后缀,那么贡献的方案数就是 1 + 2 + ... + (x - 1),统计最大值:维护最大值和次大值,最小值和次小值,更新答案。
这种方法的复杂度主要看数据,如果数据很乱,导致 Height数组的最大值很小,那么这种方法就可以过,否则就会 TLE。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 300005;
const long long INF = 9223372036854775807;
typedef long long LL;
int n, a[MAX_N], sa[MAX_N], r[MAX_N], h[MAX_N], id1, id2;
LL val[MAX_N], Mx, Mxx, Mn, Mnn;
int ws[MAX_N], wv[MAX_N], wa[MAX_N], wb[MAX_N];
LL add[MAX_N], ans, ret;
void da(int *a, int *sa, int n, int m) {
int *x = wa, *y = wb;
for (int i = 0; i < m; i ++) ws[i] = 0;
for (int i = 0; i < n; i ++) ws[x[i] = a[i]] ++;
for (int i = 1; i &l