top1编程
← 返回题目
题解

统计字符

1 条题解

  • 0
    @ 2026-8-6 0:54:22

    P4653 统计字符(入门)

    解题思路

    第一步,明确题目要什么。 题目给了一串只由小写字母组成的字符串,要统计 a 到 z 每个字母各出现了多少次。

    第二步,开一个计数器数组。 我们开一个长度为 26 的数组 letterCnt,约定 letterCnt[0] 表示字母 'a' 的个数,letterCnt[1] 表示 'b' 的个数,……,letterCnt[25] 表示 'z' 的个数。

    第三步,学会"字符变下标"的魔法。 用 str[i]-'a' 就可以把字母变成数组下标。比如字符 'c','c'-'a'=2,所以它应该加到 letterCnt[2] 上。遍历字符串的每一个字符,找到对应的下标加 1,统计就完成了。这样我们不需要去记 ASCII 码的具体数值,用减法一切就变得很自然。

    第四步,按顺序输出。 把 letterCnt[0] 到 letterCnt[25] 按顺序输出,中间用空格隔开,一共 26 个整数。

    第五步,用样例验证。 拿样例 "abbcccxyz" 来说:a 出现 1 次,b 出现 2 次,c 出现 3 次,x、y、z 各出现 1 次,其他字母都是 0 次。所以输出第一项是 1,第二项是 2,第三项是 3,中间是一长串 0,最后是 1 1 1,和样例完全一致。

    第六步,处理空输入的边界情况。 如果输入的字符串是空的,程序应该什么都不输出,直接结束。代码中先把字符数组初始化为空,再用 cin>>str 的返回值判断读取是否成功:如果读取失败就直接返回,不输出任何内容。这样即使评测数据里出现空串,程序也不会乱输出东西,更不会访问到未初始化的数组内容。学会处理边界情况,是写程序时很重要的能力,很多同学就是栽在没考虑空输入上。

    参考代码

    // P4653 统计字符:统计字符串中 a~z 每个字母出现的次数
    #include <iostream>
    using namespace std;
    
    char str[1005] = "";
    int letterCnt[26];
    
    int main() {
        if (!(cin >> str)) return 0; // 输入为空时直接结束,不输出任何内容
        for (int i = 0; str[i] != '\0'; i++) letterCnt[str[i] - 'a']++;
        for (int i = 0; i < 26; i++) {
            if (i > 0) cout << " ";
            cout << letterCnt[i];
        }
        cout << endl;
        return 0;
    }
    

    复杂度分析

    只需要从头到尾扫描一次字符串,时间 O(len),len 最大 1000;输出固定是 26 个数。空间上只用一个 letterCnt[26] 数组,是 O(1)。无论怎么算都非常快。

    • 1