题目
思路
首先这道题的题意我当时给曲解了,题目中说是字典序最小的,所以我以为是比如说BACDEF…XYZABCDEFG…XYZ这种序列选第二个,但是又说是最左侧的,我就在想为什么最左侧还有不同的答案,看了样例才明白不同的答案是指?的填充按照字典序最小的方式。
我们设置了两个数组,vis表示26个字母每一个是否已经取过,pos表示26个字母分别对应在字符串的哪个位置。核心做法是每次遇到重复的字母就把l移到目前l到i之间该字母第一次出现的位置+1,表示从这个地方重新开始记录字符串,并且把原来l到重新开始的地方之间的字母从那两个数组中取消记录。最后输出的时候遇到?就从A开始判断哪个字母不存在,遇到第一个不存在的字母填第一个?,第二个不存在的填第二个?
代码
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
string s;
int l=0,r=0;
bool vis[26];//记录是否访问
int pos[26];//记录每个字母的位置
void bianli(){
cin>>s;
for(int i=0;i<s.size();i++){
if(s[i]=='?'){
if(i-l==25){
r=i;
break;
}
else
continue;
}
else{
if(!vis[s[i]-'A']){
vis[s[i]-'A']=true;
pos[s[i]-'A']=i;
}
else{
while(l<=pos[s[i]-'A']){
vis[s[l]-'A']=false;
pos[s[l]-'A']=-1;
l++;
}
pos[s[i]-'A']=i;
vis[s[i]-'A']=true;
}
if(i-l==25){
r=i;
break;
}
}
}
}
int main()
{
for(int i=0;i<26;i++){
vis[i]=false;
pos[i]=-1;
}
bianli();
if(r==0)
cout<<"-1"<<endl;
else{
while(l<=r){
if(s[l]=='?'){
int i=0;
while(i<26){
if(!vis[i])
break;
i++;
}
vis[i]=true;
char zimu='A'+i;
cout<<zimu;
}
else
cout<<s[l];
l++;
}
}
return 0;
}