[2019CCPC秦皇岛] J MUV LUV EXTRA KMP

给出一个字符串,并且给出参数 a , b a,b a,b。然后对于这个字符串的一个可以通过在后面增补字符而构成循环节的一个子串。它的长度为 l l l,它的整个循环在当前串中出现的长度为 p p p,求最大的 a p − b l ap-bl apbl
事实上对于从 i i i这个后缀选择的任何前缀, p p p的值是固定的一定是后缀的长度,所以对于后缀选定的情形下,自然是 l l l尽量小。
所以要求一个后缀的最小循环节,考虑将串倒置,求前缀的最小循环节。用kmp求出next数组,循环节长度为i-next[i]。
枚举后缀更新答案。

#include 
using namespace std;
typedef long long ll; 
const int N=1e7+3;
char s[N],t[N];
int p=0;
int nxt[N];
int main() {
	ll a,b;
	scanf("%lld%lld",&a,&b); 
	scanf("%s",s+1);
	int n=strlen(s+1);
	for(int i=n;i>=1;i--) {
		if(s[i]=='.') break;
		t[p++]=s[i];
	}
	nxt[0]=-1;
	int j=-1,i=0;
	int len=p+1;
	while(i<len) {
		while(j!=-1&&t[i]!=t[j]) j=nxt[j];
		nxt[++i]=++j;
	}
	ll ans=a-b;
	for(int i=1;i<=p;i++) 
		ans=max(ans,a*i-b*(i-nxt[i]));
	printf("%lld\n",ans);
	return 0;
}

你可能感兴趣的:(比赛题解)