喵哈~!主人,今天我们来看一道超级可爱的题目,叫做 "Pangram" 呢。别看它名字有点怪,其实是个很简单的字符串问题哦。让本猫娘来给你好好讲讲吧,喵~
题目大意
这道题是关于一种叫做 “全字母句” (Pangram) 的东西,听起来是不是很厉害的样子?一个全字母句,就是指一个句子或者单词,它把字母表里所有的字母(在这个问题里就是英语字母 a 到 z)都至少包含了一次,喵。
题目会给我们一个字符串,里面有大写和小写的英文字母。我们需要判断这个字符串是不是一个全字母句。大小写是不区分的哦,也就是说 'a' 和 'A' 都算是字母 'a'。如果字符串包含了从 'a' 到 'z' 的所有26个字母,我们就输出 "YES",否则就输出 "NO",就这么简单呢。
举个栗子:
"toosmallword"
-> 里面缺了好多字母,所以是 "NO"。"TheQuickBrownFoxJumpsOverTheLazyDog"
-> 这句话可是非常有名的全字母句哦,它包含了所有26个字母,所以是 "YES"。
解题方法
要判断是不是全字母句,最直接的思路就是检查从 'a' 到 'z' 这26个字母是不是都在字符串里出现过,对吧?
本猫娘的思路是这样的,喵~:
一个快速的小判断:一个合格的全字母句,至少得有26个字符才能装下所有字母呀。所以,如果给我们的字符串长度
n
小于26,那它肯定不是全字母句啦!直接输出 "NO" 就可以跑路了,嘿嘿。标记字母是否出现:我们需要一个东西来记录哪些字母已经出现过了。一个大小为26的布尔数组
letters_found
就很合适!数组的第0个位置对应字母'a',第1个位置对应'b',以此类推,直到第25个位置对应'z'。一开始,把它们全都设为false
,表示我们一个字母都还没找到呢。遍历字符串:接下来,我们一个一个地看输入字符串里的每个字符。
- 因为题目不区分大小写,所以不管拿到的是大写还是小写,我们都先把它统一转换成小写字母。比如 'A' 变成 'a','B' 变成 'b'。
- 然后,根据这个小写字母,找到它在布尔数组里对应的位置(比如
小写字母 - 'a'
),然后把那个位置的值改成true
。这就像是在小本本上打个勾,表示“这个字母我找到啦!”
最终检查:等我们把整个字符串都检查完之后,再回头看看我们的布尔数组小本本。从头到尾检查一遍,如果发现有任何一个位置的值还是
false
,那就说明对应的那个字母从没出现过,呜呜... 这就不是全字母句,输出 "NO"。完美收官:如果检查完整个布尔数组,发现所有位置都是
true
,那就太棒啦!说明所有26个字母都到齐了,这就是一个完美的全字母句!输出 "YES",任务完成,喵~!
题解代码
这是用 C++ 实现的代码,本猫娘加上了中文注释,方便主人理解哦。
#include <iostream>
#include <string>
#include <vector>
#include <cctype> // 包含 tolower 函数,用来转换小写字母
#include <set> // 虽然这个解法没用 set,但它也是一种很好的选择哦
// 主函数,程序从这里开始执行喵
int main() {
// 这两行是为了让输入输出更快一点,是竞赛中的一个小技巧呢
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
// 读取字符串的长度
std::cin >> n;
std::string s;
// 读取字符串本身
std::cin >> s;
// 一个小小的优化:如果字符串长度小于26,肯定凑不齐所有字母,直接说NO
if (n < 26) {
std::cout << "NO\n";
return 0; // 程序结束
}
// 创建一个大小为26的布尔向量,用来记录a-z是否出现过
// 初始值都是 false,表示都还没找到
std::vector<bool> letters_found(26, false);
// 遍历输入的字符串 s 中的每一个字符 ch
for (char ch : s) {
// 不管字符是大写还是小写,都统一转成小写
char lower_ch = std::tolower(ch);
// 计算这个小写字母对应的索引 (比如 'a' -> 0, 'b' -> 1)
// 然后把 letters_found 数组中对应位置标记为 true
letters_found[lower_ch - 'a'] = true;
}
// 遍历我们的标记数组 letters_found
for (bool found : letters_found) {
// 如果发现有任何一个字母没有被找到 (标记仍然是 false)
if (!found) {
// 那就说明这不是一个全字母句,输出 "NO" 然后结束程序
std::cout << "NO\n";
return 0;
}
}
// 如果循环顺利结束,说明所有字母都被找到了!
// 这就是一个全字母句,输出 "YES"
std::cout << "YES\n";
return 0; // 优雅地结束程序,喵~
}
知识点介绍
这道题虽然简单,但也用到了几个很有用的小知识点呢,主人快来学习一下!
全字母句 (Pangram) 这个概念本身就是一个知识点啦。它指包含了字母表中所有字母的句子。除了题目里的例子,还有一个很经典的
"Sphinx of black quartz, judge my vow."
也是哦。大小写转换
std::tolower()
在处理英文字符串时,经常会遇到需要忽略大小写的情况。C++ 的<cctype>
头文件里提供了std::tolower()
和std::toupper()
两个函数,分别可以把一个字符转成小写和大写。超级方便的,对吧?使用布尔数组进行标记 用一个布尔数组来记录一组成员(比如26个字母)是否存在,是一种非常常见且高效的技巧。它本质上是一种最简单的哈希表(或者叫位图),数组的索引直接对应我们要检查的元素。因为索引计算非常快 (
char - 'a'
),所以这个方法效率很高。另一种思路:使用集合
std::set
除了用布尔数组,我们还可以用 C++ 的std::set
容器来解决这个问题。set
是一个会自动排序且不允许重复元素的集合。- 我们可以遍历输入字符串。
- 把每个字符都转成小写,然后插入到
set
中。 - 因为
set
会自动处理重复,所以不管一个字母出现多少次,最终在set
里只会有一个。 - 遍历结束后,我们只需要检查一下
set
的大小(set.size()
)。如果大小等于26,就说明所有字母都出现过,是全字母句!这种方法代码写起来可能更简洁一些,也是很棒的思路呢。
好啦,这次的题解就到这里啦!是不是很简单很有趣呢?主人下次遇到类似的题目,一定也能轻松解决的,喵~!