#KMP,dp#洛谷 3426 [POI2005]SZA-Template

题目

给定一个字符串\(S\),字符串可以理解成一条每个字母代表一种颜色的线段,
找到一个长度最小的串\(T\),使得在若干位置放置\(T\)后使得字符串被完全覆盖


分析

显然它要么取\(i\),要么取\(dp[fail[i]]\)可以使得答案尽量短,
那么判断一下如果当前位置如果能有交集那么用\(dp[fail[i]]\)更新答案


代码

#include <cstdio>
#include <cstring>
#define rr register
using namespace std;
const int N=500011; char s[N];
int fail[N],dp[N],last[N],n;
signed main(){
	scanf("%s",s+1),n=strlen(s+1);
	for (rr int i=2,j=0;i<=n;++i){
		while (j&&s[i]!=s[j+1]) j=fail[j];
		if (s[i]==s[j+1]) ++j;
		fail[i]=j;
	}
	dp[1]=last[1]=1;//NOTICE
	for (rr int i=2;i<=n;++i){
		dp[i]=i;
		if (last[dp[fail[i]]]>=i-fail[i]) dp[i]=dp[fail[i]];
		last[dp[i]]=i;
	}
	return !printf("%d",dp[n]);
}
posted @ 2020-12-09 17:39  lemondinosaur  阅读(50)  评论(0编辑  收藏  举报