Lougu P3804 【模板】后缀自动机

题目描述

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

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

输入输出格式

输入格式:

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

输出格式:

一个整数,为 所求答案

输入输出样例

输入样例#1:

abab

输出样例#1:

4

说明

对于10%10%的数据,|S|<=1000∣S∣<=1000
对于100%100%的数据,|S|<=10^6∣S∣<=10
6

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
const int M = N << 1;
typedef long long LL;
char s[N];
int cur = 1,node = 1,n,last;
int ch[M][27],fa[M],len[M],size[M];
LL ans;
void Build(int c, int id){
	last = cur; cur = ++ node; //node 是总节点数。cur是当前节点,last 是上一个节点。
	int p = last; len[cur] = len[last] + 1;
	for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = cur;
	//这个是 next 指针。沿着 fail 指针一直向前找。
	if (!p) fa[cur] = 1; else { //如果找到根节点了。就直接 连接 fail 指针,
		int q = ch[p][c];
		if (len[q] == len[p] + 1) fa[cur] = q; else{ //满足条件,连接fail指针.
			int nt = ++node; len[nt] = len[p] + 1; //不满足条件,新加一个节点。
			memcpy(ch[nt],ch[q],sizeof(ch[q])); // 把 q 节点的情况 copy 给新加的 节点。
			fa[nt] = fa[q]; fa[q] = fa[cur] = nt;
			for (; ch[p][c] == q; p = fa[p]) ch[p][c] = nt;
		}
	}
	size[cur] = 1;
}
int c[N],sa[N<<1];
void flower(){
	for (int i = 1; i <= node; ++i) c[len[i]]++;
	for (int i = 1; i <= n; ++i) c[i] += c[i-1];
	for (int i = node; i > 0; --i) sa[c[len[i]]--] = i; //相当于 后缀数组的桶排序。
	for (int i = node; i; --i){
		int p = sa[i];
		if (size[p] > 1) ans = max(ans,1ll*size[p]*len[p]); //找 乘积最大。长度和出现次数。
		size[fa[p]] += size[p];
	}
}
int main(){
	scanf("%s",s+1); n = strlen(s+1);
	for (int i = 1; i <= n; i++) Build(s[i] - 'a',i);
	flower();
	printf("%lld\n",ans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值