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

# 后缀数组(SA)

洛谷 P3809 【模板】后缀排序

#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)

#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;
}