Week--8 CSP模拟 B HRZ学英语

题目原文

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

AB??EFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABDCEFGHIJKLMNOPQRSTUVWXYZ

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

输入格式

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

输出格式

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

样例输入1
ABC??FGHIJK???OPQR?TUVWXY?
样例输出1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
样例输入2
AABCDEFGHIJKLMNOPQRSTUVW??M
样例输出2
-1
数据点 字符串长度
1,2,3 24
4,5,6 10000
7,8,9,10 106

解题思路

本题要求如果存在连续的26个字母,则输出字典序最小的选择,否则输出-1。

定义结构体存储输入的每个字符和其对对应的位置(从1开始记录),定义l 和r(初始值均为1)记录当前选中字符串的左右两个位置,每读入一个字符,r++。

利用judge函数的opt=1操作将当前字母的位置存储,并用a[]给对应字母打上标记。如果输入过程中遇到了已经打上标记的字母,则从t中获取该字母前一次出现的位置,并将t之前的字母标记清空,且l=t+1,再将当前位置标记。

由于结束时r会多加一次,所以当r-l=26时说明找到了对应字符串,直接break退出,若直到输入结束,r-l(取出字符个数)仍小于26说明不存在指定字符串。

由于要求最小字典序输出。故输出时如果遇到"?",就扫描标记数组a[],找到第一个未被标记的字母,并打上标记(可以省去),记录当前标记的位置,下次再遇到“?”就从标记位置继续往后查找下一个未被标记字母。

实现代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 10;
struct word {
    char x;
    int index;
}m[maxn];
int t = 0;
bool a[28];//标记选取的26个子母出现次数
int b[28];//标记每个字母最近位置 
char c[28] = { '0','A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
bool judge(word p, int& t, int opt) {//1为放入,0为取出
    if (opt == 1)
    {
        if (p.x == '?')
        {
            return 1;
        }

        int q = p.x - 'A' + 1;
        if (p.x == c[q] && a[q] == 1)
        {
            t = b[q];
            return 0;
        }

        if (p.x == c[q] && a[q] != 1)
        {
            b[q] = p.index;
            a[q] = 1;
            return 1;
        }

    }
    else if (opt == 0)
    {
        if (p.x == '?')
        {
            //s--;
            return 1;
        }
        int q = p.x - 'A' + 1;
        if (p.x == c[q] && a[q] == 1)
        {
            b[q] = 0;
            a[q] = 0;
            return 0;
        }

    }

}

int main()
{
    int i = 0;
    int l = 1, r = 1;
    memset(m, 0, sizeof(m));
    while (scanf("%c", &m[++i].x) != EOF)
    {
        if (r - l == 26)
            break;
                //判断输入是否结束
        if (m[i].x != '?' && (m[i].x<'A' || m[i].x>'Z'))
            break;

        m[i].index = i;
        int d; 
        if (!judge(m[i], t, 1))
        {
            for (int j = l; j < t+1; j++)
                judge(m[j], t, 0);
                judge(m[i], d, 1);
            l = t + 1;
        }
        r++;
    }
    if (r - l < 26)
    {
        cout << -1 << endl;
        //cout << r << " " << l << endl;
        exit(0);
    }
    else if (r - l == 26)
    {
        int k = 1;
        for (int i = l; i <r; i++)
        {
            if (m[i].x == '?')
            {
                for (int j = k; j <= 26; j++)
                {
                    if (a[j] == 0)
                    {
                        k = j + 1;
                        printf("%c", c[j]);
                        a[j] = 1;
                        break;
                    }

                }
            }
            else
            {
                printf("%c", m[i].x);
            }
        }
    }
    cout << endl;
    return 0;
}

小结

选用适宜的基础算法可以更快地解决问题,如果本题采用尺举法计算会比自己想算法更加快捷简单,消耗时间会大大减少。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,761评论 0 5
  • 算法 尺取法 题目描述 给出一个数列,找出数列中第一个出现的位置连续的且由26个字母构成的字符串(26个字母可以任...
    musanri阅读 161评论 0 1
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,713评论 0 4
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 4,132评论 0 2
  • 获取目录的方法 Environment类的描述Provides access to environment var...
    passssssss阅读 280评论 0 0

友情链接更多精彩内容