P3804 后缀自动机模版
Posted acerkoo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3804 后缀自动机模版相关的知识,希望对你有一定的参考价值。
题意
给定一个只包含小写字母的字符串 S,
请你求出 S 的所有出现次数不为 1 的子串的出现次数乘上该子串长度的最大值。
思路
后缀自动机,parent树上dfs。
code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
const int maxm = maxn<<1;
long long ans = 0;
struct SAM
int len[maxm], link[maxm], cnt[maxm];
int a[maxm], c[maxm];
int nxt[maxm][26];
int last, tot;
int head[maxm], v[maxm], nt[maxm], num;
void addEdge(int u, int _v)
v[num] = _v, nt[num] = head[u];
head[u] = num++;
// vector<int> g[maxn<<1];
void init()
len[0] = link[0] = 0;
last = tot = 1;
void extend(int c)
c -= 'a';
int cur = ++tot, p = last;
len[cur] = len[last] + 1;
cnt[cur] = 1;
for (; p && !nxt[p][c]; p = link[p]) nxt[p][c] = cur;
if(!p)
link[cur] = 1;
else
int q = nxt[p][c];
if(len[q] == len[p]+1)
link[cur] = q;
else
int clone = ++tot;
len[clone] = len[p] + 1;
memcpy(nxt[clone], nxt[q], sizeof(nxt[q]));
link[clone] = link[q];
for (; p!=-1 && nxt[p][c]==q; p=link[p]) nxt[p][c] = clone;
link[q] = link[cur] = clone;
last = cur;
void build()
for (int i = 1; i <= tot; ++i) head[i] = -1; num = 0;
for (int i = 2; i <= tot; ++i)
addEdge(link[i], i);
void dfs(int x) // parent树上dfs, vector T了, 前向星2.98s, mx = 494ms
for (int i = head[x]; ~i; i=nt[i])
dfs(v[i]);
cnt[x] += cnt[v[i]];
if(cnt[x] > 1) ans = max(ans, 1ll*cnt[x]*len[x]);
void count() // 利用基数排序模拟dfs过程 , 3.65s, mx = 982ms
long long ans = 0;
for (int i = 1; i <= tot; ++i) ++c[len[i]];
for (int i = 1; i <= tot; ++i) c[i] += c[i-1];
for (int i = 1; i <= tot; ++i) a[c[len[i]]--] = i;
for (int i = tot; i; --i)
int p = a[i];
cnt[link[p]] += cnt[p];
if(cnt[p]>1) ans = max(ans, 1ll*cnt[p]*len[p]);
printf("%lld\n", ans);
sam;
char str[maxn];
int main()
sam.init();
scanf("%s", str);
for (int i = 0; str[i]; ++i) sam.extend(str[i]);
sam.build();
sam.dfs(1);
printf("%lld\n", ans);
// sam.count();
return 0;
以上是关于P3804 后缀自动机模版的主要内容,如果未能解决你的问题,请参考以下文章