后缀自动机SAM【模板】

>Link

luogu P3804


>Description

给定一个只包含小写字母的字符串S,
请你求出 S 的所有出现次数不为 1 的子串的出现次数乘上该子串长度的最大值。

∣ S ∣ ≤ 1 0 6 |S|\le 10^6 S106


>解题思路

在我题单里躺了好久,终于学了,我太蒻了qwq

大佬的博客

(注意这里是有两个结构的,parent tree和后缀自动机,要根据它们的性质灵活运用)
这道题要求的是最大的出现次数*长度
对于一个节点,这里的串的 e n d p o s endpos endpos 都是相同的(出现次数相同),那要最大肯定优先取 l e n len len(最长的串的长度)
然后因为在parent tree中,父亲节点的 e n d p o s endpos endpos 是被几个儿子分割的,也就是 ∣ e n d p o s ( f a ) ∣ = ∑ ∣ e n d p o s ( s o n ) ∣ |endpos(fa)|=\sum |endpos(son)| endpos(fa)=endpos(son),这可以直接用个树形DP解决


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2000010
#define LL long long
using namespace std;

struct node
{
    
    
	int len, f, son[30];
	node(){
    
    memset (son, 0, sizeof (son)), len = f = 0;}
} t[N];
struct edge
{
    
    
	int to, nxt;
} e[N];
int n, tot, cnt, h[N], f[N], last;
LL ans;
string s;

void add_edge (int u, int v) {
    
    e[++cnt] = (edge){
    
    v, h[u]}; h[u] = cnt;}
void add (int x)
{
    
    
	int p = last, np = last = ++tot; //last按顺序加的上一个前缀的位置
	t[np].len = t[p].len + 1;
	f[tot] = 1; //只有新加一个字符时,endpos才会出现新的数值
	for (; p && !t[p].son[x]; p = t[p].f) t[p].son[x] = np; //连边
	if (!p) t[np].f = 1;
	else
	{
    
    
		int q = t[p].son[x];
		if (t[q].len == t[p].len + 1) t[np].f = q; //q是np的后缀,直接连边
		else //新建一个点来平分q,使得nq是np的后缀且与q性质相同
		{
    
    
			int nq = ++tot;
			t[nq] = t[q]; t[nq].len = t[p].len + 1;
			t[q].f = t[np].f = nq;
			for (; p && t[p].son[x] == q; p = t[p].f)
			  t[p].son[x] = nq;
		}
	}
}
void dfs (int now)
{
    
    
	for (int i = h[now]; i; i = e[i].nxt)
	{
    
    
		dfs (e[i].to);
		f[now] += f[e[i].to];
	}
	if (now != 1 && f[now] > 1)
	  ans = max (ans, (LL)f[now] * (LL)t[now].len);
}

int main()
{
    
    
//	freopen ("P3804_2.in", "r", stdin);
	cin >> s;
	n = s.size(), s = " " + s;
	tot = last = 1;
	for (int i = 1; i <= n; i++) add (s[i] - 'a' + 1);
	for (int i = 2; i <= tot; i++) add_edge (t[i].f, i);
	dfs (1);
	printf ("%lld", ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_43010386/article/details/121181158