不打算写太多的讲解了(其实是我也说不清楚QwQ),这里只贴一份代码留着以后抄

# 后缀数组(SA)

洛谷 P3809 【模板】后缀排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;
char s[N];
int sa[N], rk[N], hei[N], x[N], y[N], cnt[N];
int n, m = 127, tmp[N];

inline void update(int Rk[], int tp[]){
for(int i = 1; i <= m; ++i) cnt[i] = 0;
for(int i = 1; i <= n; ++i) cnt[Rk[tp[i]]]++;
for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
for(int i = n; i; --i) sa[cnt[Rk[tp[i]]]--] = tp[i];
}

inline void build_sa(){
int *Rk = rk, *tp = tmp;
for(int i = 1; i <= n; ++i) Rk[i] = s[i], tp[i] = i;
update(Rk, tp);
int p = 1;
for(int len = 1; p < n; m = p, len <<= 1){
p = 0;
for(int i = n - len + 1; i <= n; ++i) tp[++p] = i;
for(int i = 1; i <= n; ++i)
if(sa[i] > len) tp[++p] = sa[i] - len;
update(Rk, tp);
swap(Rk, tp);
Rk[sa[1]] = p = 1;
for(int i = 2; i <= n; ++i)
Rk[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]]) && (tp[sa[i] + len] == tp[sa[i - 1] + len]) ? p : ++p;
}
for(int i = 1; i <= n; ++i) rk[sa[i]] = i;
for(int i = 1, j = 0; i <= n; hei[rk[i++]] = j)
for(j = j ? j - 1 : j; s[i + j] == s[sa[rk[i] - 1] + j]; ++j);
}

int main(){
scanf("%s", s + 1);
n = strlen(s + 1);
build_sa();
for(int i = 1; i <= n; ++i) printf("%d%c", sa[i], "\n "[i != n]);
return 0;
}

# 后缀自动机(SAM)

P3804 【模板】后缀自动机 (SAM)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <bits/stdc++.h>
#define ll long long

using namespace std;

namespace IO{
inline int read(){
int x = 0;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}

template <typename T> inline void write(T x){
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;

const int N = 2e6 + 10;
int n, lst = 1, tot = 1;
int len[N], siz[N], ch[N][27], fa[N];
char s[N];

inline void insert(int c){
int p = lst, np = ++tot;
lst = np;
len[np] = len[p] + 1, siz[np]++;
while(p && !ch[p][c]) ch[p][c] = np, p = fa[p];
if(!p) return fa[np] = 1, void();
int q = ch[p][c];
if(len[q] == len[p] + 1) return fa[np] = q, void();
int nq = ++tot;
len[nq] = len[p] + 1, fa[nq] = fa[q], siz[nq] = 0;
for(int i = 0; i < 26; ++i) ch[nq][i] = ch[q][i];
while(p && ch[p][c] == q) ch[p][c] = nq, p = fa[p];
fa[q] = fa[np] = nq;
}

vector <int> g[N];
int ans = 0;

inline void dfs(int x){
for(auto y : g[x]) dfs(y), siz[x] += siz[y];
if(siz[x] > 1) ans = max(ans, siz[x] * len[x]);
}

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 <= tot; ++i) g[fa[i]].push_back(i);
dfs(1);
write(ans), puts("");
return 0;
}