美团点评2016研发工程师在线笔试题解一

总共六道编程题,先从第5题写吧,因为比较有成就感,原题是在牛客网做的,刚开始不会做,

不过看了讨论区的讨论,看不懂怎么做的,有用动态规划的,有用二进制的,各路大神都有,

虽然通过了牛客的测试,但是我试了几个例子,居然输出负数,无奈只好自己做了,花了一整天

按我自己的思路做了出来,自己还算比较才满意。

题目描述:求字典序在s1和s2之间的,长度在len1到len2的字符串的个数,结果mod1000007

输入描述:每组数据包含s1(长度小于100),s2(长度小于100),len1(小于100000),len2(大于len1,小于100000)

输出描述:输出答案

示例

输入: ab  ce  1  2

输出:56

示例分析:所求字符串str的字典序在ab和ce之间,长度在1到2之间,满足条件的有ac~az,ba~bz,b,c,ca~cd,共计24+26+2+4=56个(个人觉得题目没什么理解难度,不知道为什么很多人不理解题目)。

解析:我解答是首先是从一个测试样例开始的,因为我的代码第一个测试样例不过,str1=cpqejrrgp, str2=cpqejtrdg,len1=9,len2=9(输出应该为35064)。

第一步:首先找到两个字符串str1和str2相对位置第一个不相同的位置,若以示例中的例子为例ab和ce,第一个相对位置不相等的位置下标为0即a和c不相等,用k记录位置下标,若以我的第一个测试样例为例,str1=cpqejrrgp和str2=cpqejtrdg,第一个相对不相等的位置下标为5,即k=5时,str1[k]=r,str2[k]=t,二者第一次不相等。当找到第一个相对位置不相等的下标k;

第二步:先求在k位置处,所求字符串的str[k]>str1[k] && str[k]<str2[k]的情况有多少种,这个是最好算的,只要满足str[k]>str1[k]&&str[k]<str2[k],后面的位置可以在a~z之间随便取。例如str1=cpqejrrgp,str2=cpqejtrdg,str[5]>r && str[5]<t 即str[5]=s时,后面的三个位置str[6],str[7],str[8]随意取,共有pow(26,len1-1-k)种,若len2>len2,还需要写一个for循环,pow函数中的参数需要从len1-1-k到len2-1-k分别计算,最后累加,代表str的长度分别为len1,len1+1,.....,len2时各有多少种;

第三步:其次再求str[k]==str1[k]时str有多少种。此时,str1[k+1]需大于str1[k+1],str[k+2]、str[k+3]、...、str[len2-1]可以随意取;接着再求str[k]==str1[k] && str[k+1]==str1[k+1]时str有多少种,此时str[k+2]需大于str1[k+2],str[k+3].....str[len2-1]可以随便取,以此类推,直到str[k]==str1[k]&&str[k+1]&&..&&str[len2-2]==str1[len2-2]为止,将所有计算情况相加;

第四步:再次计算str[k]==str2[k]时str有多少种,此时,str[k+1]需小于str2[k+1],str[k+2]....str[len2-1]可以随意取值;再接着求str[k]==str2[k]&&str[k+1]==str2[k+1]时,str[k+2]...str[len2-1]位置可以随意取;以此类推,直到求出str[k]==str2[k] && str[k+1]==str2[k+1] && ...&& str[len2-2]==str2[len2-2]为止,所有情况数累加;

第五步:把第二步、第三步、第四步的所有情况累加取模,即可求出总数(注意求解过程中的边界问题一定要判断好,且无论如何,输出不可能为负数,测试样例1:abbv abba 4 4,应输出:0;测试样例2:ab ce 1 2,应输出:56;测试样例3:cpqejrrgp cpqejtrdg 9 9 输出:35064;测试样例4:a b 1 1 输出:0)。

牛客练习网址可测试:https://www.nowcoder.com/questionTerminal/f72adfe389b84da7a4986bde2a886ec3点击打开链接

#include<iostream>
#include<string>
#include<math.h>
using namespace std;
int main() {
	string str1, str2;
	int len1, len2;
	while (cin >> str1 >> str2 >> len1 >> len2) {
		if (str1.length() < len2)
			str1.append(len2 - str1.size(), 'a'-1);
		if (str2.length() < len2)
			str2.append(len2 - str2.size(), 'z'+1);
		long long sum = 0;
		int k = 0;
		while (str1[k] == str2[k] && k < len2)
		{
			k++;
		}
		if (str1[k] < str2[k] && len1 <= len2)
		{
			for (int i = len1-1; i < len2; i++)
			{
				if (i == k)
				{
					if (k == len1 - 1 && k==len2-1)
						sum += str2[k] - str1[k] - 1;
					else
						sum += str2[k] - str1[k];
				}
				else
					sum += (str2[k] - str1[k] - 1)*pow(26, i - k);
			}
			k++;
			for (int i = len1; i <= len2; i++)
			{			
				//str[k]==str1[k]时的种数,注意当str1.size()<len1的时候
				//后面的计算
				for (int j = k; j < i; j++)
				{
					sum += ('z' - str1[j])*pow(26, i - j - 1);
				}
				//str[k]==str2[k]时的种数,注意当str2.size()>len2的时候
				//后面的计算
				for (int j = k; j < i; j++)
				{
					sum += (str2[j] - 'a')*pow(26, i - j - 1);
				}
			}
		}
		cout << sum << endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值