程序设计思维(CSP模拟题)B - HRZ 学英语

题目

瑞神今年大三了,他在寒假学会了英文的26个字母,所以他很兴奋!
于是他让他的朋友TT考考他,TT想到了一个考瑞神的好问题:给定一个字符串,从里面寻找 连续的26个大写字母 并输出!
但是转念一想,这样太便宜瑞神了,所以他加大了难度:现在给定一个字符串,字符串中包括26个大写字母和特殊字符’?’,特殊字符’?'可以代表任何一个大写字母。
现在TT问你是否存在一个 位置连续的且由26个大写字母组成的子串 ,在这个子串中每个字母出现且仅出现一次,如果存在,请输出从左侧算起的第一个出现的符合要求的子串,并且要求,如果有多组解同时符合位置最靠左,则输出字典序最小的那个解!如果不存在,输出-1!
这下HRZ蒙圈了,他刚学会26个字母,这对他来说太难了,所以他来求助你,请你帮他解决这个问题,报酬是可以帮你打守望先锋。
说明:字典序 先按照第一个字母,以 A、B、C……Z 的顺序排列;如果第一个字母一样,那么比较第二个、第三个乃至后面的字母。如果比到最后两个单词不一样长(比如,SIGH 和 SIGHT),那么把短者排在前。例如

AB??EFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABDCEFGHIJKLMNOPQRSTUVWXYZ

上面两种填法,都可以构成26个字母,但是我们要求字典序最小,只能取前者。
注意,题目要求的是 第一个出现的, 字典序最小的 !

Input
输入只有一行,一个符合题目描述的字符串。

Output
输出只有一行,如果存在这样的子串,请输出,否则输出-1

Sample input1
ABC??FGHIJK???OPQR?TUVWXY?

Sample output1
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Sample input2
AABCDEFGHIJKLMNOPQRSTUVW??M

Sample output2
-1

思路

设输入的字符串为str。
建立一个数组visit[26]。若visit[i]=true,则说明第i个字母存在。

for (Left从0遍历到str.length - 26) {
	memset(visit, false, sizeof(visit));

	Right = Left + 26;

	for (k从Left到Right遍历) {
		if (visit[str[k] - 'A']) 说明str[Left]到str[Right]存在同一个字母出现了两次及以上的情况,str[Left]到str[Right]不符合要求;
		else if (str[k] >= 'A' && str[k] <= 'Z') visit[str[k] - 'A'] = true;
	}

	if (不符合要求) continue;

	for (i从Left到Right遍历) {
		if (str[i] == '?') str[i] = 最小的visit == false的字母;
	}

	输出str;
}

代码

#include <iostream>
#include <cstring>

using namespace std;

string str;
bool visit[26]; //visit[0]使用,代表'A'
bool solve;

int Left, Right;
int cnt;

void print()
{
	for (int i = 0; i < 26; i++)
		if (visit[i]) {
			char c = 'A' + i;
			cout << c << " ";
		}
	cout << endl;
}

int find()
{
	for (int i = Left; i < Right; i++)
		if (str[i] == '?') return i;
	return -1;
}

int main()
{
	cin >> str;

	Left = 0;
	Right = 25;

	for (Left = 0; Left < str.length() - 25; Left++) {
		memset(visit, false, sizeof(visit));
		solve = true;
		Right = Left + 26;
		for (int k = Left; k < Right; k++) {
			if (visit[str[k] - 'A']) solve = false;
			else if (str[k] >= 'A' && str[k] <= 'Z') visit[str[k] - 'A'] = true;
		}

		//cout << "1" << endl;

		if (!solve) continue;

		//cout << "Left: " << Left << " " << "Right: " << Right << endl;

		//print();

		for (int i = Left; i < Right; i++) {
			if (!visit[i - Left]) {
				char c = 'A' + i - Left;
				int in = find();
				//cout << in << endl;
				str[in] = c;
			}
		}

		//cout << "2" << endl;

		for (int i = Left; i < Right; i++)
			cout << str[i];
		cout << endl;


		return 0;
	}

	cout << "-1" << endl;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值