2019 CCPC 秦皇岛: MUV LUV EXTRA

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)

上一篇:HDU 1824 Let's go home


下一篇:事务的四个属性ACID