CSP-M2补题_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
ABC??FGHIJK???OPQR?TUVWXY?
AABCDEFGHIJKLMNOPQRSTUVW??M

Sample Output

ABCDEFGHIJKLMNOPQRSTUVWXYZ
-1

思路分析

此题做法类似于滑动窗口,窗口大小为26。首先用sum[]数组记录每种字母和"?“的个数,然后遍历sum[]数组,若每个字母次数均未超过1次,则按字典序补齐”?"输出;否则,向后移动窗口(l++,r++)。

代码

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

const int maxn=1e6+5;
char s[maxn],tmp[27];
int sum[27]={0};//记录窗口内每个字母出现次数
int l=0,r=25;//双指针

int check()
{//检查合法
    for(int i=0;i<26;i++)
    {//某个字母出现多于一次则不合法
        if(sum[i]>1) 
            return 0;
    }
    return 1;
}
void output()
{ 
    int index=0;
    for(int i=0;i<26;i++)
    {
        if(sum[i]==0)
        {//按字典序最小插入字母,存到tmp数组中
            tmp[index]=char('A'+i); 
            index++;
  	} 
    }
    index=0;
    for(int i=l;i<=r;i++)
    {//遍历数组s[],遇到"?"输出tmp[]中的字母,遇到字母则正常输出
  	if(s[i]=='?') 
   	    cout<<tmp[index++];
    	else cout<<s[i];
    }
    cout<<endl;
}

int main()
{
    cin>>s;
    int len=strlen(s);
    for(int i=0;i<26;i++)
    {
        if(s[i]=='?') sum[26]++;
        else{//从sum[0]开始存储每个字母出现次数
   	    sum[s[i]-'A']++; 
  	}
    }
    while(r<len){
        if(check()){//合法则输出
   	    output();
   	    return 0;
    	} 
  	else{//不合法,指针右移
   	    if(s[l]=='?')
    		sum[26]--;
  	    else{
    		sum[s[l]-'A']--;
   	    }
   	    l++;
    	    r++;
      	    if(r<len){
    		if(s[r]=='?')
     		    sum[26]++;
    		else sum[s[r]-'A']++;
   	    } 
  	}
    } 
    cout<<-1<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSP-J(China Software Cup-Java组)是一个全国级的编程竞赛,每年都会举办复赛。复赛的题目通常在算法、数据结构、程序设计等方面,要求选手提供高效的解决方案。下面是对各年度CSP-J复赛真题的回答。 CSP-J复赛真题每年都有不同的主题和难度,涵盖了各种计算机科相关领域的知识。它们旨在考察选手在问题建模、算法设计和实现能力上的综合素质。 对于每一年的真题,选手都需要理解题目要求,分析问题特点,提出合适的解题思路。然后,他们需要实现算法,编写代码,并进行测试以确保解决方案的正确性和效率。最后,选手需要在规定的时间内,提交他们的解答。 CSP-J的真题经过层层筛选,旨在选拔出具有优秀编程技巧和创新思维的选手。参加CSP-J真题的选手必须具备扎实的编程基础知识,并能够迅速的学习和运用新的技术。通过参加CSP-J竞赛,选手不仅可以提升自己的技术水平,还能够锻炼团队合作和问题解决的能力。 CSP-J复赛真题的发布旨在鼓励生独立思考和创新,培养他们在实际问题中运用计算机知识解决问题的能力。它不仅对参赛选手有很大的挑战,也对其他编程爱好者提供了学习的机会。 总之,CSP-J复赛真题是一项计算机编程竞赛,通过解答真实的问题,考察参赛选手在算法设计和执行能力上的综合素质。参加这项竞赛可以锻炼选手的编程能力,并提供展示才能的平台。它对于促进计算机科领域的创新发展和人才培养起到了积极的促进作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值