P3804-[模板]后缀自动机【SAM】

正题

题目链接:https://www.luogu.com.cn/problem/P3804


题目大意

长度为 n n 的串,求一个出现次数不小于2的子串使得子串长度乘上出现次数最大。


解题思路

构建 S A M SAM 的时候统计一下每个子串出现多少次即可。


c o d e code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e6+10;
int n,cnt,num[N],len[N],fail[N],next[N][26],ans;
char s[N];
void New_Point(int x,int y){
	next[x][y]=++cnt;
	len[cnt]=len[x]+1;
}
void Make_SAM(char *s){
	int last;
	cnt=last=num[1]=1;
	for(int i=1;i<=n;i++){
		int val=s[i]-'a';
		New_Point(last,val);
		int x=last,y;last=next[x][val];
		for(y=fail[x];y;y=fail[y])
			if(!next[y][val]) next[y][val]=last;
			else{
				if(len[y]+1==len[next[y][val]])
					fail[last]=next[y][val];
				else{
					int z=next[y][val];
					New_Point(y,val);
					fail[cnt]=fail[z];
					num[cnt]=num[z];
					fail[last]=fail[z]=cnt;
					for(int i=0;i<26;i++)
						next[cnt][i]=next[z][i];
					for(int w=y;w;w=fail[w])
						if(next[w][val]==z)
							next[w][val]=cnt;
				}
				break;
			}
		if(!y)fail[last]=1;
		for(y=last;y;y=fail[y])
			num[y]++;
	}
	return;
}
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	Make_SAM(s);
	for(int i=1;i<=cnt;i++)
		if(num[i]>1)
			ans=max(ans,num[i]*len[i]);
	printf("%d",ans);
}
发布了867 篇原创文章 · 获赞 55 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/104085485