SP8222 NSUBSTR - Substrings
知识点: SAM
原题面 Luogu
分析题意
SAM 板子背诵检查。
按拓扑序求出每个状态出现次数,仅更新 \(F(\operatorname{len}(i))\)。
长的包含短的,显然有 \(F(i) = \max\limits_{j=i+1}^{n}\{F(j)\}\)。
代码实现
//知识点:SAM
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define ll long long
const int kMaxn = 5e5 + 10;
const int kMaxm = 26;
//=============================================================
int n, last = 1, node_num = 1, f[kMaxn];
int ch[kMaxn << 1][kMaxm], link[kMaxn << 1], len[kMaxn << 1], size[kMaxn << 1];
int edge_num, v[kMaxn << 1], ne[kMaxn << 1], head[kMaxn << 1];
char S[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-') f = - 1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
void AddEdge(int u_, int v_) {
v[++ edge_num] = v_, ne[edge_num] = head[u_], head[u_] = edge_num;
}
void Insert(int c_) {
int p = last, now = last = ++ node_num;
size[now] = 1, len[now] = len[p] + 1;
for (; p && ! ch[p][c_]; p = link[p]) ch[p][c_] = now;
if (! p) {link[now] = 1; return ;}
int q = ch[p][c_];
if (len[q] == len[p] + 1) {link[now] = q; return ;}
int newq = ++ node_num;
memcpy(ch[newq], ch[q], sizeof (ch[q]));
link[newq] = link[q], len[newq] = len[p] + 1;
link[q] = link[now] = newq;
for (; p && ch[p][c_] == q; p = link[p]) ch[p][c_] = newq;
}
void Dfs(int u_) {
for (int i = head[u_]; i; i = ne[i]) {
Dfs(v[i]);
size[u_] += size[v[i]];
}
GetMax(f[len[u_]], size[u_]);
}
//=============================================================
int main() {
scanf("%s", S + 1);
n = strlen(S + 1);
for (int i = 1; i <= n; ++ i) Insert(S[i] - 'a');
for (int i = 2; i <= node_num; ++ i) AddEdge(link[i], i);
Dfs(1);
for (int i = n; i >= 1; -- i) GetMax(f[i], f[i + 1]);
for (int i = 1; i <= n; ++ i) printf("%d\n", f[i]);
return 0;
}
作者@Luckyblock,转载请声明出处。

浙公网安备 33010602011771号