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 Input 1
ABC??FGHIJK???OPQR?TUVWXY?
Sample Output 1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Sample Input 2
AABCDEFGHIJKLMNOPQRSTUVW??M
Sample Output 2
-1
Note
时间限制 | 1s |
---|---|
空间限制 | 64mb |
数据点 | 字符串长度 |
---|---|
1,2,3 | 26 |
4,5,6 | 104 |
7,8,9,10 | 106 |
题解
用类似尺取的方法,有一个左指针和右指针,区间内长度为26,每次移动一格。用长度为26的letter数组来记录目前区间中分别含有26个字母的个数,用wenhao来记录目前区间中含有’?‘的个数。
一开始取前26个字母,并计算出这26个字母中的letter数组和wenhao,并判断这26个字母能否符合要求。不符合则r和l右移,进入循环。进入while循环后,先将l-1处的字母在letter数组或wenhao中删除,再将r处的字母计入letter数组或wenhao。然后判断这26个字母能否符合要求。不符合则r和l右移,进入下一次循环。循环直至r>n时结束。
判断某26个字母是否符合要求时,判断letter数组中是否所有元素小于1即可。若满足这个条件,需要将最小序列输出。输出时,首先循环letter数组,将letter数组中为0的元素插入数组v中(这段字符串中没有这个元素,这些元素的顺序可变);然后对v排序,使字典序小的元素在前;然后循环l到r区域,输出相应字母,’?'处有序输出相应的v数组中的元素。一旦判断成功后,输出后直接结束程序即可。运行到程序末尾则证明没有符合要求的元素,输出-1。
代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
char a[1000100];
int letter[26];
int wenhao=0;
vector<int>v;
int main(int argc, char** argv) {
scanf("%s",a);
memset(letter,0,sizeof(letter));
int n=strlen(a);
//计算前26个
int l=0,r=25;
for(int i=0;i<26;i++){
if(a[i]=='?'){wenhao++;continue;}
letter[a[i]-'A']++;
}
//判断前26个
bool suc=1;
for(int i=0;i<26;i++){
if(letter[i]>1){suc=0;break;}
}
if(!suc){l++;r++;}
else{//成功
for(int i=0;i<26;i++){
if(letter[i]==0){
v.push_back(i);
}
}
sort(v.begin(),v.end());
int tot=0;
for(int i=l;i<=r;i++){
if(a[i]=='?'){
printf("%c",'A'+v[tot++]);
}else{
printf("%c",a[i]);
}
}
printf("\n");
return 0;
}
while(r<n){
//计算
if(a[l-1]=='?'){wenhao--;}
else{letter[a[l-1]-'A']--;}
if(a[r]=='?'){wenhao++;}
else{letter[a[r]-'A']++;}
//检查 判断
suc=1;
for(int i=0;i<26;i++){
if(letter[i]>1){suc=0;break;}
}
if(!suc){l++;r++;}
else{//成功
for(int i=0;i<26;i++){
if(letter[i]==0){
v.push_back(i);
}
}
sort(v.begin(),v.end());
int tot=0;
for(int i=l;i<=r;i++){
if(a[i]=='?'){
printf("%c",'A'+v[tot++]);
}else{
printf("%c",a[i]);
}
}
printf("\n");
return 0;
}
}
printf("-1\n");
return 0;
}