题目
瑞神今年大三了,他在寒假学会了英文的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;
}