Week 8 CSP M2 HRZ学英语

题目描述

瑞神今年大三了,他在寒假学会了英文的26个字母,所以他很兴奋!于是他让他的朋友TT考考他,TT想 到了一个考瑞神的好问题:给定一个字符串,从里面寻找连续的26个大写字母并输出!但是转念一想, 这样太便宜瑞神了,所以他加大了难度:现在给定一个字符串,字符串中包括26个大写字母和特殊字 符’?’,特殊字符’?'可以代表任何一个大写字母。现在TT问你是否存在一个位置连续的且由26个大写字 母组成的子串,在这个子串中每个字母出现且仅出现一次,如果存在,请输出从左侧算起的第一个出现 的符合要求的子串,并且要求,如果有多组解同时符合位置最靠左,则输出字典序最小的那个解!如果 不存在,输出-1! 这下HRZ蒙圈了,他刚学会26个字母,这对他来说太难了,所以他来求助你,请你帮 他解决这个问题,报酬是可以帮你打守望先锋。
说明:字典序 先按照第一个字母,以 A、B、C……Z 的顺序排列;如果第一个字母一样,那么比较第二 个、第三个乃至后面的字母。如果比到最后两个单词不一样长(比如,SIGH 和 SIGHT),那么把短者排 在前。例如

AB??EFGHIJKLMNOPQRSTUVWXYZ 
ABCDEFGHIJKLMNOPQRSTUVWXYZ 
ABDCEFGHIJKLMNOPQRSTUVWXY

上面两种填法,都可以构成26个字母,但是我们要求字典序最小,只能取前者。
注意,题目要求的是 第一个出现的,字典序最小的!

样例

Input

输入只有一行,一个符合题目描述的字符串。 

Output

输出只有一行,如果存在这样的子串,请输出,否则输出-1 

样例输入1

ABC??FGHIJK???OPQR?TUVWXY?

样例输出1

ABCDEFGHIJKLMNOPQRSTUVWXYZ

样例输入2

AABCDEFGHIJKLMNOPQRSTUVW??M

样例输出2

-1

思路

首先一串字符串在判断时应该是26个一组进行判断的
①对于长度小于26的字符串,必然不满足条件
②对于长度为26的字符串,遍历字符串,使用数组记录每个字符出现的次数和“?”出现的次数,遍历数组,如果每个字母都没有重复(出现次数<=1)并且“?”出现的次数恰好等于出现次数为0的字母的个数,那么此时满足条件
③如果长度大于26,我们要选取最靠左的并且满足条件的子字符串,从第一个字母开始,向后遍历26个字母,并进行②判断,如果满足条件,则选取这一段,如果不满足条件,后移一个字母继续进行③判断,直至出现符合条件的字符串或者遍历结束

对于输出满足条件的字符串:另设一数组,在遍历记录字母出现次数的数组时,依次将次数为0的字母记录到新数组中,在输出时,遇到“?”就依次按顺序输出该数组中记录的字母

代码

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;


int main()
{
	string s;
	cin>>s;
//	cout<<int(s[0]);
	int sum1[26]={0};
	int sum2[26]={0};
	int n=s.size();
	int num=0;//用来统计?数量 
	for(int i=0;i<n;i++)
	{
		if(s[i]!='?')
		{
			sum1[int(s[i])-65]++;
		}
		else num++;	
	}
	if(n==26)//123数据点 
	{
		int index=0;
		int a[26]; 
		int k=0,p=0;
		for(int i=0;i<n;i++)
		{
			if(sum1[i]>=2)
			{
				index=1;//重复不符合要求 
			} 
			else if(sum1[i]==0)
			{
				num--;
				a[k]=i+65;
				k++;
			}	
		}
		if(index==0&&num==0)//不重复且缺失的字母能用?补上 
		{
			for(int i=0;i<n;i++)
			{
				if(s[i]!='?')
					cout<<s[i];
				else
				{
					cout<<char(a[p]);
					p++;
				}
			}
		}
		else cout<<"-1"<<endl;	
	}
	else
	{
		int flag=n;
		int p=0;
		int a[26];//用来记录那些字母没有 
		for(int i=0;i<n-24;i++)
		{
			int sum2[26];
			memset(sum2,0,sizeof(sum2));
			int num2=0;
		//	int a[26];
			memset(a,0,sizeof(a));
			int q=0;
			
			//统计各个字母的出现次数 
			for(int j=i;j<i+26;j++)
			{
				if(s[j]!='?')
					sum2[int(s[j])-65]++;
				else
				{
					num2++;//问号数++ 
				}	
			}

			
			int index=0;
			for(int k=0;k<26;k++)
			{
				if(sum2[k]>=2)
				{
					index=1;
				}
				else if(sum2[k]==0)
				{
					num2--;
					a[q]=k+65;
					q++;
				}
			}
			if(index==0&&num2==0)
			{
				flag=i;
				break;
			}
		}
		if(flag!=n)
		{
			for(int i=flag;i<flag+26;i++)
			{
				if(s[i]!='?')
					cout<<s[i];
				else
				{
					cout<<char(a[p]);
					p++;
				} 
			}
		cout<<endl;
		}
		else cout<<"-1"<<endl;		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yySakura

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值