洛谷P3804 后缀自动机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/82845799

题目描述

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

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

输入输出格式

输入格式:

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

输出格式:

一个整数,为 所求答案

输入输出样例

输入样例#1: 复制

abab

输出样例#1: 复制

4
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define ll long long
const int maxm = 1000005;
#define M 26
struct node
{
	int link, len, Next[M], val;
}st[maxm * 3];
char str[maxm];
int cnt, last, c[maxm * 3], a[maxm * 3], s[maxm * 3];
void init()
{
	memset(st, 0, sizeof(st));
	cnt = 1, last = 0;
	st[0].link = -1;
}
void insert(int c)
{
	int p = last, now = cnt++, rev;
	st[now].len = st[p].len + 1;
	s[now] = 1;
	while (p != -1 && !st[p].Next[c])
		st[p].Next[c] = now, p = st[p].link;
	if (p == -1) st[now].link = 0;
	else
	{
		int q = st[p].Next[c];
		if (st[q].len == st[p].len + 1)
			st[now].link = q;
		else
		{
			rev = cnt++;
			st[rev] = st[q];
			st[rev].len = st[p].len + 1;
			while (p != -1 && st[p].Next[c] == q)
				st[p].Next[c] = rev, p = st[p].link;
			st[q].link = st[now].link = rev;
		}
	}
	last = now;
}
int main()
{
	int n, i, j, k, sum;
	init();
	scanf("%s", str);
	for (i = 0;str[i] != '\0';i++)
		insert(str[i] - 'a');
	ll ans = 0;
	for (i = 1;i < cnt;i++) c[st[i].len]++;
	for (i = 1;i < cnt;i++) c[i] += c[i - 1];
	for (i = 1;i < cnt;i++) a[c[st[i].len]--] = i;
	for (i = cnt - 1;i >= 1;i--)
	{
		int p = a[i];
		s[st[p].link] += s[p];
		if (s[p] > 1)
			ans = max(ans, (ll)s[p] * st[p].len);
	}
	printf("%lld\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/82845799