Problem A. MUV LUV EXTRA(kmp求最小循环节)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Problem A. MUV LUV EXTRA(kmp求最小循环节)相关的知识,希望对你有一定的参考价值。

LINK

最小化 a ∗ p − b ∗ l a*p-b*l apbl

其中 p p p表示循环节总长, l l l表示循环节长度

若循环节从 i i i位置开始,那么一定需要延续到末尾


考虑固定循环节总长度 p p p,也就是需要最小化 l l l

转化一下题意,现在循环节总长是 [ i , n ] [i,n] [i,n]

我们要找到最小的 j j j满足 [ i , j ] [i,j] [i,j] [ i , n ] [i,n] [i,n]的循环节

[ i , n ] [i,n] [i,n]可以表示为 s s s s b ssssb ssssb的形式

其中 s s s是最小循环节, b b b s s s的前缀,如何找到 s s s的长度??

我们发现 s s s s b ssssb ssssb的最长公共前后缀刚好是 s s s b sssb sssb

也就是 s s s s b − s s s b = s ssssb-sssb=s ssssbsssb=s

就是循环节总长-最长公共前后缀即是最小循环节

所以倒着求一遍 k m p kmp kmp即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e7+10;
int A,B,n,be,kmp[maxn];
char a[maxn],b[maxn];
int main()
{
	scanf("%d%d%s",&A,&B,b+1);
	n = strlen( b+1 );
	for(int i=1;i<=n;i++)
		if( b[i]=='.' )	be = i;
	for(int i=be+1;i<=n;i++)	a[i-be] = b[i];	
	n -= be;
	reverse( a+1,a+1+n );
	int j = 0;
	for(int i=2;i<=n;i++)
	{
		while( j&&a[j+1]!=a[i] )	j = kmp[j];
		if( a[j+1]==a[i] )	j++;
		kmp[i] = j;
	}
	long long ans = -1e18;
	for(int i=1;i<=n;i++)
	{
		int p = i;//循环节总长度 
		ans = max( ans,1ll*A*p-1ll*B*(p-kmp[i]) );
	}
	cout << ans;
}

以上是关于Problem A. MUV LUV EXTRA(kmp求最小循环节)的主要内容,如果未能解决你的问题,请参考以下文章

Gym102361K MUV LUV UNLIMITED

HDU 6741 MUV LUV UNLIMITED (博弈论)

2019 China Collegiate K. MUV LUV UNLIMITED(思维,博弈)

2019 CCPC秦皇岛 J 题 MUV LUV EXTRAKMP 求最小循环节

2019 CCPC秦皇岛 J 题 MUV LUV EXTRAKMP 求最小循环节

Problem A. Balanced Fighters