MUV LUV EXTRA
(本篇主要内容,kmp求最短循环节)
题目传送门:
MUV LUV EXTRA
题意:
给你一个字符串和两个整数a和b。在小数点后,找到一个循环节 l,循环长度为p。求 a * p - b * l 的最大值。
思路:
我们容易想到的是,当循环长度§确定时,我们要找到最小的循环节(l),那么这时a * p - b * l 的值在该循环长度下肯定是最大的。因为题目要求是要至少循环一次且字符串的末尾正在循环中,所以我们枚举循环长度p时,要先把字符串倒置过来。然后接下去很好处理啦,kmp求最小循环节即可。
AC Code
//kmp从后往前找最短循环节
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e7+10;
char str[N],cpy[N];
int F[N];
int main()
{
LL a,b;
while(scanf("%lld%lld%s",&a,&b,str)!=EOF)
{
int len=strlen(str);
int ans=0;
for(int i=len-1;i>=0;i--)
{
if(str[i]=='.') break;
cpy[ans++]=str[i];
}
F[0]=-1;
for(int i=1;i<ans;i++)
{
int j=F[i-1];
while(j>=0&&cpy[j+1]!=cpy[i])
j=F[j];
if(cpy[j+1]==cpy[i])
F[i]=j+1;
else F[i]=-1;
}
LL maxn=-1e12;
for(int i=0;i<ans;i++)
{
LL k=i-F[i];
maxn=max((i+1)*a-b*k,maxn);
}
printf("%lld\n",maxn);
}
//system("pause");
return 0;
}
(目前正在做一些CCPC的题,希望一个月之后不会打铁QAQ)