题目大意:给一个只包含小写字母的字符串 $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 ", ans); return 0; }