Problem A. MUV LUV EXTRA(kmp求最小循环节)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Problem A. MUV LUV EXTRA(kmp求最小循环节)相关的知识,希望对你有一定的参考价值。
最小化 a ∗ p − b ∗ l a*p-b*l a∗p−b∗l
其中 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 ssssb−sssb=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求最小循环节)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6741 MUV LUV UNLIMITED (博弈论)
2019 China Collegiate K. MUV LUV UNLIMITED(思维,博弈)
2019 CCPC秦皇岛 J 题 MUV LUV EXTRAKMP 求最小循环节