Skip to content

ProblemListheOnlyLovelyProblem - 题解

标签与难度

标签: 字符串处理, 基础算法, 模拟, 条件判断, C++ 难度: 800

题目大意喵~

你好呀,未来的算法大师!这道题是关于一个叫 Dreamoon 的学长,他特别喜欢 "lovely" 的东西,喵~

在他眼里,一个字符串是 "lovely" 的,当且仅当这个字符串是以 "lovely" 这个单词开头的。最重要的一点是,这个判断是不区分大小写的哦!比如说,"LovelyDay"、"lovely_cat" 甚至 "LOVELY" 都算是 "lovely" 的字符串。

我们的任务就是,给定一个字符串,帮助 Dreamoon 判断它是不是 "lovely" 的。如果是,就输出 "lovely";如果不是,就输出 "ugly",呐~

解题思路分析

这道题的核心就是要判断一个字符串的前缀,听起来是不是很简单呀?让我带你一步一步拆解它,喵~

第一步:长度的守护结界!

一个字符串要想以 "lovely" 开头,它自身的长度至少也得有 6 个字符吧?("l-o-v-e-l-y" 正好是6个字母)。如果一个字符串,比如 "cat",长度连 6 都不到,那它肯定不可能以 "lovely" 开头啦。所以,我们可以设置一个“守护结界”:

首先检查输入字符串的长度,如果小于 6,直接判定为 "ugly",然后就可以结束程序啦! 这样既能处理掉一类情况,也能防止我们后面访问不存在的字符(比如对一个长度为3的字符串访问第4个字符)导致程序出错,非常安全,喵~

第二步:大小写的魔法转换!

题目要求我们不区分大小写。比如,对于第一个字符,无论是 'l' 还是 'L',都应该被接受。

一种直接的想法是,对每个位置都进行两次判断,就像这样: if (s[0] == 'l' || s[0] == 'L') { ... } 然后对第二个字符也做 if (s[1] == 'o' || s[1] == 'O') { ... } ... 这样一层一层嵌套下去,代码会变得又长又乱,像一团缠住的毛线球,一点都不可爱!

有没有更优雅的办法呢?当然有啦!我们可以施展一个“大小写统一”的魔法!在比较之前,我们先把输入字符串的前 6 个字符全部转换成小写。这样一来,无论原始输入是 "Lovely..."、"lOvElY..." 还是 "LOVELY...",它们的前 6 个字符经过转换后,都会变成清一色的 "lovely"。

然后,我们只需要把这个转换后的结果和标准的小写 "lovely" 进行比较就可以啦!是不是瞬间就简单多啦?

最终的作战计划!

总结一下我们的作战计划,喵~

  1. 读入字符串:使用 C++ 中更安全、更方便的 std::string 来存储输入的字符串。
  2. 长度检查:判断字符串长度是否小于 6。如果是,直接输出 "ugly" 并返回。
  3. 逐个字符比较:我们写一个循环,从第 0 个字符到第 5 个字符,一共 6 个。在循环里,我们做两件事:
    • tolower() 函数把当前位置的输入字符变成小写。
    • 把它和我们心中的标准 "lovely" 字符串对应位置的字符进行比较。
  4. 得出结论
    • 如果在循环中,有任何一个字符对不上(比如输入 "lovfly",第3个字符 'f' 就不等于 'e'),那就说明它不是 "lovely" 的,我们立刻输出 "ugly" 并结束程序。
    • 如果循环顺利跑完了 6 次,所有字符都完美匹配,那就说明这个字符串确实是以 "lovely" 开头的!我们就在循环结束后输出 "lovely"。

这个思路清晰又高效,让我们来实现它吧,呐!

代码实现

这是我根据上面的思路,精心为你准备的一份代码哦~ 注释超详细的!

cpp
#include <iostream> // 用于输入输出,比如 cin 和 cout
#include <string>   // 用于使用 std::string 类,处理字符串更方便喵~
#include <cctype>   // 提供了 tolower() 函数,可以把大写字母变成小写

int main() {
    // 为了更快的输入输出,虽然这题数据量小,但养成好习惯总是好的~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    // 定义一个目标字符串,这是我们的判断标准
    const std::string target = "lovely";
    
    // 定义一个变量来接收输入的字符串
    std::string input_str;
    std::cin >> input_str;

    // 第一步:检查长度!这是最重要的防御性编程~
    // target.length() 的值是 6
    if (input_str.length() < target.length()) {
        std::cout << "ugly" << std::endl;
        return 0; // 不满足条件,直接结束程序
    }

    // 第二步:逐个字符进行不区分大小写的比较
    bool is_lovely = true; // 先假设它是 lovely 的
    for (int i = 0; i < target.length(); ++i) {
        // tolower(input_str[i]) 会把输入字符串的第 i 个字符转为小写
        // target[i] 本身就是小写
        // 如果在任何一个位置,转换后的字符不等于目标字符...
        if (tolower(input_str[i]) != target[i]) {
            is_lovely = false; // ...那它就不是 lovely 的
            break;             // 已经确定不是了,就没必要继续比较了,直接跳出循环!
        }
    }

    // 第三步:根据比较结果输出
    if (is_lovely) {
        std::cout << "lovely" << std::endl;
    } else {
        std::cout << "ugly" << std::endl;
    }

    return 0; // 程序圆满结束啦,喵~
}

复杂度分析

  • 时间复杂度: O(1)O(1) 我们最多只关心输入字符串的前 6 个字符。无论输入的字符串有多长(比如一百万个字符),我们的循环最多也只会执行 6 次。所以,花费的时间是一个固定的、很小的常数,与输入规模无关,因此时间复杂度是 O(1)O(1) 的说。

  • 空间复杂度: O(1)O(1) 我们只用到了几个固定大小的变量(target 字符串,input_str 字符串,is_lovely 布尔值等)。input_str 的空间取决于输入,但这是必要的存储,不计入额外空间。我们算法本身使用的额外空间是常数级别的,所以空间复杂度也是 O(1)O(1),喵~

知识点总结

通过这道可爱的小题目,我们学会了:

  1. std::string 的使用:在 C++ 中,使用 std::string 比传统的 C 风格 char 数组更安全、功能更强大。
  2. cctype 头文件:它包含了很多有用的字符处理函数,比如 tolower()(转小写)和 toupper()(转大写),是处理大小写不敏感问题的利器!
  3. 防御性编程:在处理数组或字符串时,首先检查索引是否会越界(比如本题中的长度检查),是一个非常重要的好习惯。
  4. 算法思想 - 归一化:将不同形式(大写、小写)的数据统一转换成一种标准形式(全部小写)再进行比较,是一种非常常用且高效的简化问题的策略。

希望这篇题解能帮到你,继续加油哦,你超棒的!喵~