目录

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

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

题目:

题目描述:

给定一个只包含小写字母的字符串$S$,

请你求出 $S$ 的所有出现次数不为 $1$ 的子串的出现次数乘上该子串长度的最大值。

输入格式:

一行一个仅包含小写字母的字符串$S$

输出格式:

一个整数,为 所求答案

样例:

样例输入 1:

1
abab

样例输出 1:

1
4

思路:

实现:

 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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "ybwhead/ios.h"
long long ans;
int n, nl;
const int maxn = 3 * 1e6 + 100;
char s[maxn];
struct sam
{
    int mp[maxn][26];
    struct edge
    {
        int nxt, v;
    } e[maxn];
    int tot, cnt, las, len[maxn], head[maxn], siz[maxn], fa[maxn];
    void add(int u, int v)
    {
        e[++tot].v = v;
        e[tot].nxt = head[u];
        head[u] = tot;
    }
    void ins(int c)
    {
        int p = las;
        siz[las = ++cnt] = 1;
        len[las] = nl;
        for (; p && mp[p][c] == 0; p = fa[p])
        {
            mp[p][c] = las;
        }
        if (p == 0)
        {
            fa[las] = 1;
            return;
        }
        int q = mp[p][c];
        if (len[p] + 1 == len[q])
        {
            fa[las] = q;
            return;
        }
        len[++cnt] = len[p] + 1;
        for (int i = 0; i < 26; i++)
        {
            mp[cnt][i] = mp[q][i];
        }
        fa[cnt] = fa[q];
        fa[q] = cnt;
        fa[las] = cnt;
        for (int i = p; mp[i][c] == q; i = fa[i])
        {
            mp[i][c] = cnt;
        }
    }
    inline void jt()
    {
        for (int i = 2; i <= cnt; i++)
        {
            add(fa[i], i);
        }
    }
    void dfs(int u)
    {
        for (int i = head[u]; i; i = e[i].nxt)
        {
            dfs(e[i].v);
            siz[u] += siz[e[i].v];
        }
        if (siz[u] != 1)
        {
            ans = max(ans, (long long)siz[u] * len[u]);
        }
    }
} sam;
int main()
{
    scanf("%s", s + 1);
    n = strlen(s + 1);
    sam.cnt = sam.las = 1;
    for (nl = 1; nl <= n; nl++)
        sam.ins(s[nl] - 'a');
    sam.jt();
    sam.dfs(1);
    yout << ans << endl;
    return 0;
}