题目
样例输入1
ABC??FGHIJK???OPQR?TUVWXY?
样例输出1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
样例输入2
AABCDEFGHIJKLMNOPQRSTUVW??M
样例输出2
-1
划重点
就是找到输入序列中连续的26个字母,里面要包含从A~Z的每一个字母,不能重复,但是26个字母排列不需要连续(就是不需要A后面必须是B,B后面不需要是C这样子...)
思路
存储输入序列,然后申请一个队列q,并且设置word数组来记录某一个字母是否在队列。
遍历输入序列的每一个字符,从第一个字符开始,每读取一个元素,判断其是否为'?':
如果是'?',直接加入队列,并且不需要标记word数组;
如果不是,判断队列中是否已经存在该元素,如果存在,将此元素以及他靠近队首的元素全部出队列(如队列中已有序列ABCDEFG,现在要将D入队列,需要先将队列中的A、B、C、D依次出队列)。出队列时将出队列元素的word标记为零。出队列操作完成后,将读取元素入队列,并标记word数组。
注意:因为word数组不会对'?'进行标记,所以无法使用word数组判断队列中元素是否已经满26个,需要额外变量k记录队列元素。
代码
#include<iostream>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
bool word[26];
queue<char> q;
int main()
{
memset(word, 0, sizeof word);
string str;
cin >> str;
int k = 0;
bool is = false;
for (int i = 0; i < str.length(); i++)
{
if (k == 26) continue;
else if (str[i] == '?' || !word[str[i] - 65])
{
q.push(str[i]);
k++;
if (str[i] != '?')
word[str[i] - 65] = 1;
}
else
{
while (!q.empty() && q.front() != str[i])
{
if (q.front() != '?')
word[q.front() - 65] = 0;
q.pop();
k--;
}
if (q.front() != '?')
word[q.front() - 65] = 0;
q.pop();
k--;
q.push(str[i]);
k++;
if (str[i] != '?')
word[str[i] - 65] = 1;
}
if (k == 26)
is = true;
}
if (!is) cout << -1 << endl;
else
{
int i = 0;
for (int j = 0; j < 26; j++)
{
//cout << "j:" << j;
if (q.front() != '?')
{
cout << q.front();
q.pop();
}
else
{
for (i; i < 26; i++)
{
if (!word[i])
{
cout << (char)(i + 65);
q.pop();
word[i] = 1;
break;
}
}
}
}
}
system("Pause");
}
总结
题目真的很简单,但是题目真的很难读懂,感谢室友2333
当读不懂题目的时候,还不如直接都输出-1,没准还能多拿几分...
这种方法与尺取法的方法类似,但对我个人而言,申请一个队列比移动游标更加容易理解。