题意:
给定一个字符串,看是否有一个连续的26个的子串,其中有26个字母,如果有则输出。注意,字符顺序不需要注意,即不需要一定ABCDE…,并且其中有“?”,“?”字符可以代替任何一个字母。在最终输出这样的字符串的时候,注意将问号替换成字母,其中使得替换后的字典序最小。
input:
一个字符串。
output:
如果存在,则输出这样的最小的字典序字符串。没有的话则输出-1。
思路:
因为是找连续的字符串,想到移动窗口。即保持窗口大小26,开始移动。在读取字符的时候,可以通过将字符转成ASCII码当作数组下标,每次移动一个字符的时候,减去最左侧的字符,加上最右侧的字符。并检查标记的数组,如果从A到Z的数组中有数量为2的则不可能组成26个不同的字母。继续向右移动。当找到这样的数组的时候,则停止遍历。并遍历标记的数组,将其中的为0的字母找出来。再最后输出这个字符串的时候,如果遇到“?”则将其转成这些字母输出,得到最小字典序的子串。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int l=0;
int r=0;
char C[1000100];
int num=0;
int a[28];
char w[27];
int cw;
int f(){
for(int i=2; i<=27;i++){
if(a[i]>1) return -1;
}
return 1;
}
void output(){
cw=0;
for(int i=2;i<=27;i++){
if(a[i]==0){
w[cw]=i+63;
cw++;
}
}
int j=0;
for(int i=l;i<=r;i++){
if(C[i]!='?'){
cout<<C[i];
}else{
cout<<w[j];
j++;
}
}
cout<<endl;
}
int main(){
ios::sync_with_stdio(0);
for(int i=0; i<28;i++){
a[i]=0;
}
char c;
c=getchar();
while( num<26 && c!='\n'){
C[num]=c;
num++;
a[c-63]++;
c=getchar();
}
if(num<25){
cout<<-1<<endl;
return 0;
}
l=0;
r=25;
int cs=f();
if(cs==1){
output();
return 0;
}
while(c!='\n'){
C[num]=c;
a[C[l]-63]--;
a[c-63]++;
l++;
r++;
num++;
int cs=f();
if(cs==1){
output();
return 0;
}
c=getchar();
}
cout<<-1<<endl;
return 0;
}