题目大意:给一个只包含小写字母的字符串 $S$ ,请求出 $S$ 的所有出现次数不为 $1$ 的子串的出现次数乘上该子串长度的最大值。
题解:用后缀自动机求出每个字串的长度,排序后求出字串出现次数(后缀自动机是背板的。。。)
卡点:1.$rnk$数组没有开两倍
板背错
C++ Code:
#include <cstdio>
#include <cstring>
#define maxn 1000010
using namespace std;
char s[maxn << 1];
int nxt[maxn << 1][26], fail[maxn << 1], R[maxn << 1];
int sz[maxn << 1];
int b[maxn], rnk[maxn << 1];
int root, np, p, cnt, t, last, len;
long long ans = -1;
inline long long max(long long a, long long b) {return a > b ? a : b;}
void insert(int ch) {
int now = ++cnt, np;
R[now] = R[p = last] + 1;
sz[now] = 1; last = now;
for (; ~p && !nxt[p][ch]; p = fail[p]) nxt[p][ch] = now;
if (!~p) {fail[now] = root; return ;}
if (R[t = nxt[p][ch]] == R[p] + 1) {fail[now] = t; return ;}
R[np = ++cnt] = R[p] + 1;
for (int i = 0; i < 26; i++) nxt[np][i] = nxt[t][i];
for (fail[np] = fail[t], fail[t] = fail[now] = np; nxt[p][ch] == t; p = fail[p]) nxt[p][ch] = np;
}
int main() {
scanf("%s", s);
len = strlen(s);
fail[root = 0] = -1; cnt = last = 1;
for (int i = 0; i < len; i++) insert(s[i] - 'a');
for (int i = 1; i <= cnt; i++) b[R[i]]++;
for (int i = 1; i <= len; i++) b[i] += b[i - 1];
for (int i = 1; i <= cnt; i++) rnk[b[R[i]]--] = i;
for (int i = cnt; i; i--) {
int now = rnk[i];
sz[fail[now]] += sz[now];
if (sz[now] > 1) ans = max(ans, 1ll * sz[now] * R[now]);
}
printf("%lld\n", ans);
return 0;
}