2019CCPC秦皇岛赛区 hdu 6740 MUV LUV EXTRA(KMP next数组)

传送门

MUV LUV EXTRA

Time Limit: 2000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1586    Accepted Submission(s): 484


Problem Description
One day, Kagami Sumika is stuck in a math problem aiming at calculating the length of a line segment with given statements and constraints. Since Sumika has no idea about it, she takes out a ruler and starts to measure the length. Unfortunately, the answer is an infinite decimal and she only got the first some digits of the answer from the ruler.
Sumika guesses that the answer is a rational number, which means that there exists two integers p, q that the answer equals qp) in decimal form, denoting the first some digits of the accurate result.
It is guaranteed that there is exactly one decimal point in s and s is a legal non-negative decimal without leading "-"(the minus sign).
 

Output
Output a single line containing an integer, denoting the maximum reliability value.
 

Sample Input
  
  
5 3 1.1020 2 1 12.1212
 

Sample Output
  
  
9 6

题意:

纯夏希望从这个无限小数的前n位猜出原本的数字。纯夏意识到,猜测的循环节太长或循环节已经开始出现的部分长度太短是不可信的。举个例子,若她量出的小数为1.0285714285714,显然假设循环节为0285714285714(长度为13)或假设循环节为428571(已经开始出现的部分长度为7)都不如假设循环节为285714(长度为6,已经开始出现的部分长度为12)可靠。因此她定义一个循环节的可靠程度为a×循环节已经开始出现的部分长度−b×循环节长度。请你帮她求出最可靠的循环节的可靠程度为多少。
样例解释

对于第1组样例:

若猜测循环节为0,则可靠度=5×1−3×1=2;

其中,我们把以 0 为循环节的小数也看作无限循环小数。

若猜测循环节为20,则可靠度=5×2−3×2=4;

若猜测循环节为02,则可靠度=5×3−3×2=9;

若猜测循环节为020,则可靠度=5×3−3×3=6;

若猜测循环节为1020,则可靠度=5×4−3×4=8。

对于第2组样例:

若猜测循环节为2,则可靠度=2×1−1×1=1;

若猜测循环节为12,则可靠度=2×4−1×2=6;

若猜测循环节为21,则可靠度=2×3−1×2=4;

若猜测循环节为212,则可靠度=2×3−1×3=3;

若猜测循环节为1212,则可靠度=2×4−1×4=4。

注意,计算循环节可靠度的时候不考虑整数部分。输入中给出的整数部分只是为了还原纯夏见到的数字。
就是按照他的定义和计算方法找一下最大值

思路:

首先循环节长度,学过KMP就知道,一段字符(长度为i)的循环节长度等于i-next[i]
因为循环节在后面,所以把小数点后面的字符倒置,求一下next,然后求最大值即可
a*循环节已经开始出现的部分长度,就是当前字符串的长度
字符串从0开始的,写出i+1即可

代码:

int nex[MAXN];
char p[MAXN];
char s[MAXN];
void getnext(int nex[],char p[])
{
    int len=strlen(p);
    nex[0]=-1;
    int j=-1;
    int i=0;
    while(i<len)//原来这里是len-1,没有算到最后一个的nex,因为用的i+1,要多算一位
    {
        if(j==-1||p[i]==p[j]){
            i++,j++;
            nex[i]=j;
        }
        else
            j=nex[j];
    }
}
int main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    ll ans=-1e18;
    ll a,b;
    while(cin>>a>>b){
    	ans=-1e18;
	    cin>>s;
	    int n=strlen(s);
	    int f=0;
	    int cnt=0;
	    for(int i=0;i<n;i++){
	    	if(f==1){
	    		p[cnt++]=s[i];
	    	}
	    	if(s[i]=='.')f=1;
	    }
	    reverse(p,p+cnt);
	    for(int i=0;i<=cnt;i++)nex[i]=0;
	    getnext(nex,p);
	    for(int i=0;i<cnt;i++){
	    	//cout<<nex[i+1]<<" ";
	    	ans=max(ans,1ll*a*(i+1)-1ll*b*(i+1-nex[i+1]));
	    }
	    //cout<<endl;
	    cout<<ans<<endl;
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值