AtCode ABC249 - B - Perfect String

本文解析如何通过编程解决字符串是否为'完美'的问题,关注字符种类、大小写及唯一性的判断。通过实例演示和优化后的代码实现,探讨了不同思路和算法优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标签

  • 集合

题目地址

B - Perfect String

  • https://atcoder.jp/contests/abc249/tasks/abc249_b

问题描述

Problem Statement

Let us call a string consisting of uppercase and lowercase English alphabets a wonderful string if all of the following conditions are satisfied:

  • The string contains an uppercase English alphabet.
  • The string contains a lowercase English alphabet.
  • All characters in the string are pairwise distinct.

For example, AtCoder and Aa are wonderful strings, while atcoder and Perfect are not.

Given a string SS, determine if SS is a wonderful string.

Constraints

  • 1≤∣S∣≤100
  • S is a string consisting of uppercase and lowercase English alphabets.

Input

Input is given from Standard Input in the following format:

S

Output

If SS is a wonderful string, print Yes; otherwise, print No.


Sample Input 1

AtCoder

Sample Output 1

Yes

AtCoder is a wonderful string because it contains an uppercase English alphabet, a lowercase English alphabet, and all characters in the string are pairwise distinct.


Sample Input 2

Aa

Sample Output 2

Yes

Note that A and a are different characters. This string is a wonderful string.


Sample Input 3

atcoder

Sample Output 3

No

It is not a wonderful string because it does not contain an uppercase English alphabet.


Sample Input 4

Perfect

Sample Output 4

No

It is not a wonderful string because the 22-nd and the 55-th characters are the same.

题意

  • 完美字符串满足
    • 只包含英文
    • 至少包含一个大写和小写
    • 所有文字不重复

思路

  • 循环遍历,定义计数器,使用c++自带的函数统计大写和小写字母数量, 均不为0则满足条件;
    • 不足:这块定义一个bool变量更优
  • 循环时将每位字符存入set结构,因为set里的元素有互异性,所以最后只需要判断set的size是否和输入文字数一致即可。
    • 不足:空间复杂度上升,但处理简单,无脑就把程序写完

题解

小码匠

void coder_solution() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    string s;
    cin >> s;
    set<char> a;
    int big = 0;
    int small = 0;
    for (int i = 0; i < s.size(); i++) {
        if (isupper(s[i])) {
            big++;
        } else if (islower(s[i])){
            small++;
        }
        a.insert(s[i]);
    }
    if (a.size() == s.size() && big > 0 && small > 0) {
        cout << "Yes";
    } else {
        cout << "No";
    }
}

参考题解

void second_solution() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    string s;
    cin >> s;

    sort(s.begin(), s.end());
    for (int i = 0; i < s.length() - 1; i++) {
        if (s[i] == s[i + 1]) {
            cout << "No";
        }
    }

    bool a = false, b = false;
    for (auto &&c: s) {
        if (islower(c)) a = true;
        if (isupper(c)) b = true;
    }
    if (a && b) {
        cout << "Yes" << endl;
    }
}

官方题解

#include <bits/stdc++.h>
using namespace std;
int main() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin >> s;
    bool big = false, small = false;
    for (int i = 0; i < s.size(); i++) {
        if (isupper(s[i])) big = true;
        else small = true;
    }
    bool diff = true;
    for (int i = 0; i < s.size(); i++) {
        for (int j = i + 1; j < s.size(); j++) {
            if (s[i] == s[j]) diff = false;
        }
    }
    if (big && small && diff) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
  • 仔细分析官方题解,是有可优化空间的。
    • 第一:第8行、9行的判断中,如果bit和small都不为true,其实是没必要走后面循环处理;
    • 第二:第12行、13行用双指针来处理,更好。

待补知识点

  • 依然是函数这块,需要补充。当时看到这个题解,把代码复制到IDE中

    • 一:编译未通过,应该是自己知识水平不够,大神提交代码是没问题,功力不够;
    • 二:模板那块是自己的软肋,还没学习。
    template <class T> T scan() {
        T ret;
        std::cin >> ret;
        return ret;
    }
    
    void best_solution() {
        // 提升cin、cout效率
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        const std::string s = scan<std::string>();
    
        if (s.size() != set(s.begin(), s.end()).size()) {
            std::cout << "No" << endl;
            return;
        }
        bool upp = false;
        bool low = false;
        for (const char c: s) {
            if ('A' <= c && c <= 'Z') {
                upp = true;
            }
            if ('a' <= c && c <= 'z') {
                low = true;
            }
        }
        std::cout << (upp && low ? "Yes" : "No") << endl;
    }
    
<think>嗯,用户想用Python把输入字符串'abc EfG- 3'转换成'ABCEFG-ABCEFG-ABCEFG-'。首先,我需要理解转换的规则。输出看起来是每个字符被重复了三次,然后连在一起,但仔细看例子,可能不是这样。原输入是'abc EfG- 3',输出是三个重复的“ABCEFG-”部分。所以可能拆分后的部分需要重复三次,并且忽略数字部分? 首先,用户可能的需求是:将输入字符串中的字母部分提取出来,转成大写,然后忽略非字母字符(比如数字、符号),但保留某些符号,比如例子中的'-'被保留下来了。但原输入中有'-',输出中的每个部分都是ABCEFG-,所以可能规则是保留非字母字符,但需要处理重复次数。不过原输入中的数字3可能被用作重复次数?比如输入中的'3'对应输出的三个重复部分。 仔细看例子:输入是'abc EfG- 3',输出是三个ABCEFG-连接起来。所以可能的规则是,将字母部分提取并转成大写,然后根据输入中的数字决定重复次数。如果没有数字,可能默认一次?比如,输入中的'3'作为重复次数,所以输出重复三次,每个部分是处理后的字符串加上'-'。 那处理步骤可能是: 1. 提取输入中的所有字母,并转成大写,忽略空格和其他非字母字符,但保留符号如'-'?或者原输入中的'-'被保留在结果中。原输入中的'abc EfG- 3'处理后的字母部分是ABCEFG,然后加上-,所以可能是将字母提取出来大写,然后保留原字符串中的非字母字符中的某些部分? 或者,可能处理方式是将每个字符处理如下:字母转大写,非字母保留,但数字作为重复次数。例如,输入中的'3'是重复次数,所以结果中的每个部分是将字母和符号部分处理后的字符串,重复三次。 所以需要分解输入字符串。可能输入的三个组成部分:字母部分(包括大小写)、符号(如'-'),以及最后的数字3。需要将字母和符号部分合并为大写,然后根据数字重复次数。 例如,输入的'abc EfG- 3'分解为: 字母部分:abcEfG(转大写后为ABCEFG) 符号部分:-(保留) 数字部分:3作为重复次数。 所以处理后的每个单元是ABCEFG-,重复3次,得到ABCEFG-ABCEFG-ABCEFG-。 那如何拆分输入中的字母、符号和数字呢?或者,是否有更简单的规则? 另一种可能,用户希望将输入中的字母转换为大写,并去掉空格,然后非字母字符保留,数字作为重复次数。例如,输入中的数字3是重复次数,而其他非字母字符(如'-')保留在转换后的字符串中。然后整个转换后的字符串(包括符号)重复该次数。 所以步骤: 1. 将输入字符串中的字母转为大写,其他字符保留。 2. 提取或分割出数字部分作为重复次数,其余部分作为基础字符串。 例如,输入字符串分解为基础部分和重复次数。比如,输入中的'abc EfG- 3'中的3是重复次数,而前面的部分作为基础字符串处理。 处理基础字符串:将所有字母转大写,并去掉空格。例如,'abc EfG-'处理为'ABCEFG-',然后重复3次,得到'ABCEFG-ABCEFG-ABCEFG-'。 那如何从输入中提取重复次数?可能需要找到字符串中的数字部分,如果没有数字,默认重复一次? 所以具体步骤可能是: 1. 分割输入字符串为两部分:基础部分和重复次数。例如,可能以最后一个数字作为重复次数,或者提取所有连续的数字作为重复次数。 比如,在输入'abc EfG- 3'中,最后的3是重复次数,前面的部分是基础字符串。 如何提取?可以用正则表达式,将字符串拆分为非数字部分和数字部分。例如,使用正则表达式匹配最后的数字作为重复次数,其余部分作为基础字符串。 例如,正则表达式可以找到字符串末尾的数字,如r'(\d+)$',然后分割成基础部分和重复次数。 然后处理基础部分:将所有字母转大写,并移除非字母字符?或者保留原非字母字符,但将字母转大写? 原例中的基础部分是'abc EfG-',处理后的部分是'ABCEFG-'。所以,原字符串中的空格被移除,字母转大写,而符号'-'被保留。所以处理规则可能是:将所有字母转大写,移除非字母和非符号的字符?或者如何处理? 或者,用户希望保留所有的非数字字符(除了数字之外的字符),然后将这些字符处理为:字母转为大写,其他字符保留。例如,原输入中的空格被删除,而'-'被保留。所以,处理步骤是: 处理基础字符串部分: - 移除非数字字符中的数字吗?或者,处理基础部分时,将数字视为重复次数之外的部分? 或者更明确地说,基础部分中的任何非数字字符都会被处理,而最后的数字是重复次数。 比如,输入字符串分为两个部分:所有非数字的字符作为基础字符串,最后的数字作为重复次数。如果不存在数字,则重复次数为1。 处理基础字符串: - 将所有字母转为大写。 - 移除非字母字符?或者保留非字母字符? 原例子中的基础部分'abc EfG-'处理后的结果是ABCEFG-。原基础部分中的空格被移除了,但'-'被保留。所以,处理规则可能是:将字母转为大写,并移除非字母和非符号的字符?或者更可能的是,保留所有非数字的字符,处理字母为大写,并移除非字母中的空格? 或者,处理所有非数字的字符,将字母转大写,同时删除空格,保留其他符号如'-'。 例如,原输入的基础部分'abc EfG-'中的空格被删除,其他字母转大写,'-'保留。所以,处理后的基础字符串是ABCEFG-。 那如何实现? 可能的处理步骤: 1. 将输入字符串分割为基础部分和重复次数。例如,提取最后的数字作为次数,其余为基础部分。如果没有数字,次数为1。 例如,使用正则表达式: import re match = re.search(r'(\d+)$', input_str) 如果找到,重复次数是match.group(1),基础部分是input_str[:match.start()].strip() 否则,重复次数是1,基础部分是input_str.strip() 然后处理基础部分:将字母转为大写,其他字符保留,同时删除空格? 比如,将基础部分中的每个字符处理,如果是字母则大写,其他字符保留,但空格被删除? 例如,原基础部分是'abc EfG-',处理后的字符为每个字符处理: a→A,b→B,c→C,空格→删除,E→E,f→F,G→G,-→保留。 所以结果变成'ABCEFG-'。 这样,处理后的基础字符串是原基础部分中的每个字符,如果是字母则大写,非字母则保留,但删除空格。 或者,是否要删除所有空格?比如原输入中的空格被删除。 是的,原输入中的'abc EfG- 3'处理后变成ABCEFG-,所以空格被删除,而'-'保留。 所以处理步骤: 对于基础部分,遍历每个字符: - 如果是字母,转大写。 - 如果是空格,删除。 - 其他字符(如符号)保留。 例如,处理后的基础字符串是原基础部分中每个字符处理后的大写字母(非空格),其他符号保留,同时删除所有空格。 如何实现? 可以这样处理: processed = ''.join([c.upper() if c.isalpha() else c for c in base_part if c != ' ']) 这样,将基础部分中的每个字符,如果是字母则转为大写,非字母且不是空格的保留,空格被过滤掉。 原例子中的基础部分是'abc EfG-',经过处理后: 原字符依次是 'a','b','c',' ','E','f','G','-' 处理后的每个字符: a→A,保留;b→B,保留;c→C,保留;空格被过滤;E→E,保留;f→F,保留;G→G,保留;'-'保留。 所以结果拼接为'ABCEFG-',正确。 然后重复次数是3,所以重复三次,每个部分之间可能用连字符连接?或者直接拼接? 原例子输出是三个ABCEFG-拼接,所以每个部分是'ABCEFG-',重复三次得到'ABCEFG-ABCEFG-ABCEFG-'。 所以整个处理步骤: 输入字符串 → 分割为基础部分和重复次数 → 处理基础部分 → 重复次数次,拼接处理后的字符串。 综上,代码的大致流程是: 1. 输入字符串,如'abc EfG- 3' 2. 用正则表达式提取最后的数字作为重复次数n,其余为基础部分。 3. 处理基础部分:每个字符转为大写字母(如果是字母),保留非字母非空格字符,删除空格。 4. 将处理后的基础字符串重复n次,得到结果。 现在,需要考虑如何处理没有数字的情况。例如,输入字符串中没有数字,则n=1。 代码实现步骤: - 导入re模块。 - 输入字符串为input_str = 'abc EfG- 3' - 使用正则表达式匹配最后的数字部分: match = re.search(r'(\d+)$', input_str.strip()) 如果匹配到,n = int(match.group(1)), base_part = input_str[:match.start()].strip() 否则,n=1,base_part = input_str.strip() 然后处理base_part: processed_base = ''.join([c.upper() if c.isalpha() else c for c in base_part if c != ' ']) 然后结果字符串是 processed_base * n,但原例中是每个重复的部分都加上连字符?或者原例中的处理后的字符串是ABCEFG-,所以可能每个重复部分是完整的processed_base,然后拼接起来。例如,在例子中,processed_base是'ABCEFG-',重复三次,得到三个'ABCEFG-'的连接,即末尾没有其他符号。但原例的输出是三个'ABCEFG-'相连,所以最终的字符串是'ABCEFG-ABCEFG-ABCEFG-'。所以直接拼接即可。 因此,最终的代码应该是这样的: import re def transform_string(input_str): # 提取数字部分和基础字符串 match = re.search(r'(\d+)$', input_str.strip()) if match: n = int(match.group(1)) base_part = input_str[:match.start()].strip() else: n = 1 base_part = input_str.strip() # 处理基础部分:转大写字母,保留非字母字符(除空格外) processed = ''.join([c.upper() if c.isalpha() else c for c in base_part if c != ' ']) # 重复n次 return processed * n 测试这个函数: 输入'abc EfG- 3',处理后的base_part是'abc EfG-',处理后变成ABCEFG-,n=3,结果就是ABCEFG-重复三次,得到ABCEFG-ABCEFG-ABCEFG-,与用户给的例子相符。 那是否还有其他情况需要考虑?比如,输入中的数字可能在中间?比如,用户输入'abc3 EfG- 5',这时候正则表达式会提取最后的5作为n,而基础部分是'abc3 EfG-'。处理后的base_part中的数字3会被保留吗? 根据处理规则,非字母且不是空格的字符会被保留。例如,原处理步骤中的代码在生成processed时,会保留c.upper()如果是字母,否则保留原字符(只要不是空格)。比如,在base_part中的字符如果是数字(如3),则会被保留,因为c.isalpha()为false,所以原样保留,并且c不是空格,所以不会被过滤。这样,处理后的字符串会包含数字3,这可能不符合用户的需求? 但根据用户给出的例子,输入中的数字3作为重复次数,而基础部分中的其他字符(如符号)被保留。那如果用户输入的base部分中有数字,如何处理? 比如,输入字符串是'ab2c EfG- 3',则base_part是'ab2c EfG-',处理后变成AB2CEFG-,然后重复3次。这可能不是用户希望的,但根据当前规则,数字在基础部分会被保留,除非用户的需求是只处理字母和符号,而数字在基础部分应被删除? 但用户的问题中给出的例子并没有这样的情况,可能需要进一步确认,但根据用户的需求,可能基础部分中的数字应被忽略,只有最后的数字作为重复次数。 例如,用户可能希望基础部分中的数字被忽略,只处理字母和符号,而最后的数字作为重复次数。 那如何处理这种情况?例如,在base_part的处理中,除了空格外,还需要过滤掉数字? 这需要明确用户的需求。根据用户提供的例子,输入中的基础部分没有数字,所以可能用户的基础部分中的数字应该被删除? 或者,可能用户希望基础部分中的数字被保留,但最后的数字作为重复次数? 例如,输入'abc123- 4',则base_part是'abc123-',处理后变成ABC123-,然后重复4次。这可能不符合用户期望,但根据问题中的例子,无法确定。 但根据用户的问题描述,可能正确的方式是:在基础部分中,只保留字母和符号(非数字),而数字只在最后作为重复次数。否则,如何处理基础部分中的数字? 例如,用户可能希望基础部分中的所有数字被忽略,只处理字母和符号,而最后的数字作为重复次数。所以,处理base_part时,需要过滤掉所有数字? 或者,用户可能没有特别说明,但根据例子,基础部分中的数字可能不存在,所以代码可能需要处理这种情况。 需要用户澄清,但假设用户希望基础部分中的数字被删除,只保留字母和符号,而最后的数字作为重复次数。 那么,处理base_part时,应该过滤掉数字吗? 或者,假设用户给出的例子中的处理是正确的,可能基础部分中的数字不需要处理,直接保留? 根据用户给出的例子,基础部分中没有数字,所以无法确定。可能用户的问题中,输入中的数字仅作为重复次数,而基础部分中的其他字符(包括数字)会被处理。但这样可能会出现问题。比如,输入'abc3 EfG- 5',处理后的字符串可能包含'ABC3EFG-',这可能不是用户想要的。 为了避免歧义,可能需要进一步明确处理规则。但根据用户提供的例子,基础部分中的数字应该被保留吗? 可能用户的问题中的例子输入是'abc EfG- 3',其中基础部分中的字符是字母和符号,没有数字。而最后的数字3是重复次数。因此,代码中的处理方式可能允许基础部分中出现数字,但用户可能希望这些数字被删除? 或者,用户可能希望基础部分中的字符只包含字母和符号,而数字作为重复次数出现在末尾。因此,在基础部分中的数字应被过滤掉? 这需要调整代码,在处理base_part时,过滤掉数字。 例如,在处理base_part时,除了空格之外,还过滤掉数字? 修改代码中的处理部分为: processed = ''.join([c.upper() if c.isalpha() else c for c in base_part if c != ' ' and not c.isdigit()]) 这样,处理后的字符串将排除空格和数字,只保留字母(转为大写)和其他非数字非空格的字符。 例如,如果base_part是'ab2c- ', 则处理后的结果是'ABC-'。 这样是否更符合用户的需求? 这可能更合理,因为用户可能希望基础部分中的数字不被包含在内,只有末尾的数字作为重复次数。 但根据用户给出的例子,输入中基础部分没有数字,所以无法确定。所以,这可能是一个潜在的歧义点,需要用户确认。 但根据问题中的例子,用户希望将输入中的数字作为重复次数,而基础部分中的其他字符处理后的结果中不包含数字。例如,输入中的3被用作重复次数,而其他字符如'-'被保留。 因此,可能正确的处理方式是:在基础部分中,所有数字都被过滤掉,仅保留字母和非数字符号,而末尾的数字作为重复次数。 因此,代码需要调整处理步骤,过滤掉base_part中的数字。 所以,修改代码的处理部分: 处理base_part时,每个字符如果是字母,转为大写;否则,如果是非数字且非空格,则保留;否则(即空格或数字)被过滤掉。 所以,处理后的base_part中的字符是字母转大写,其他非数字非空格字符保留,而空格和数字被过滤。 代码修改后的处理步骤: processed = ''.join([c.upper() if c.isalpha() else c for c in base_part if c not in ' ' and not c.isdigit()]) 或者更明确的: processed = [] for c in base_part: if c == ' ': continue elif c.isdigit(): continue elif c.isalpha(): processed.append(c.upper()) else: processed.append(c) processed = ''.join(processed) 这样,base_part中的空格和数字被删除,其他字符如果是字母则大写,否则保留。 例如,输入'abc3 EfG- 3'的base_part是'abc3 EfG-',处理后的结果为'ABCEFG-',重复次数3,得到ABCEFG-重复三次,符合用户例子中的情况。 现在测试这种情况: 输入'abc3 EfG- 3' → base_part是'abc3 EfG-' → 处理后得到'ABCEFG-' → 重复3次 → 'ABCEFG-ABCEFG-ABCEFG-' 这样处理是正确的,因为base_part中的数字3被过滤掉,空格也被过滤,字母转大写,符号'-'保留。 这可能更符合用户的需求。所以,调整代码中的处理步骤。 综上,代码需要: 1. 分割输入字符串为基础部分和重复次数。 2. 处理基础部分时,过滤掉空格和数字,字母转大写,其他字符保留。 3. 重复次数由输入中的数字决定,若无则为1。 现在,编写完整的Python代码: import re def transform_string(input_str): # 提取数字部分和基础字符串 input_str = input_str.strip() match = re.search(r'(\d+)$', input_str) if match: n = int(match.group(1)) base_part = input_str[:match.start()].strip() else: n = 1 base_part = input_str # 处理基础部分:转大写字母,过滤空格和数字,保留其他字符 processed = [] for c in base_part: if c == ' ' or c.isdigit(): continue if c.isalpha(): processed.append(c.upper()) else: processed.append(c) processed_str = ''.join(processed) # 重复n次 return processed_str * n 测试这个函数: 输入'abc EfG- 3' → base_part是'abc EfG-' → 处理后的字符: a→A, b→B, c→C,空格被过滤,E→E,f→F,G→G,'-'保留 → ABCEFG- → 重复3次 → ABCEFG-ABCEFG-ABCEFG-,正确。 输入'ab2c- d5 4' → 最后的数字是4 → base_part是'ab2c- d5' → 处理时,过滤空格和数字: a→A, b→B,数字2被过滤,c→C,'-'保留,d→D,数字5被过滤 → ABC- D → 但处理后的base_part是ABC-D → 重复4次 → ABC-DABC-DABC-DABC-D. 所以,代码能够正确处理这种情况。 因此,最终的代码应该如上述所示,处理用户输入的例子正确。</think>要将输入字符串按照特定规则转换为重复的大写形式,需遵循以下步骤: ### 解决思路 1. **提取重复次数**:从字符串末尾提取数字作为重复次数,若无则默认为1。 2. **处理基础字符串**: - 移除所有空格和数字。 - 将字母转换为大写,其他符号保留。 3. **重复拼接**:将处理后的字符串按重复次数拼接。 ### 代码实现 ```python import re def transform_string(input_str): input_str = input_str.strip() # 提取末尾数字作为重复次数 match = re.search(r'(\d+)$', input_str) if match: n = int(match.group(1)) base_part = input_str[:match.start()].strip() else: n = 1 base_part = input_str # 处理基础部分:转大写字母,过滤空格和数字,保留其他符号 processed = [] for c in base_part: if c == ' ' or c.isdigit(): continue processed.append(c.upper() if c.isalpha() else c) processed_str = ''.join(processed) # 生成重复结果 return processed_str * n # 示例测试 input_str = 'abc EfG- 3' output = transform_string(input_str) print(output) # 输出: ABCEFG-ABCEFG-ABCEFG- ``` ### 代码解释 1. **正则提取数字**:使用正则表达式`r'(\d+)$`匹配字符串末尾的数字作为重复次数。 2. **字符串处理**:遍历基础部分的每个字符,过滤空格和数字,字母转大写,其他字符保留。 3. **重复拼接**:将处理后的字符串重复指定次数,得到最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小码匠和老码农

喜欢作者

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

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

打赏作者

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

抵扣说明:

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

余额充值