1. 题目背景与核心问题解析
这道来自洛谷P1321的字符串处理题目,表面上看起来简单,实则暗藏玄机。题目描述了一个初始全由点号(.)组成的字符串,随后被多次贴上"boy"或"girl"单词片段,后贴的片段会覆盖先贴的内容。最终我们看到的字符串只包含特定字符:. b g i l o r y。
题目给出的关键保证是:每个被贴上的单词至少有一个字符没有被覆盖。这意味着即使一个"boy"的'b'和'o'都被覆盖了,只要还剩下'y',我们就能确定这里曾经贴过一个"boy"。同理适用于"girl"。
这个条件实际上为我们提供了一种逆向思维的可能性——不需要完整匹配整个单词,只要找到单词的"残留痕迹"就能进行统计。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路深度剖析
2.1 基础思路:字符分类统计
最直观的解法是遍历字符串,对特定字符进行分类统计:
- 遇到b、o、y就认为存在一个boy
- 遇到g、i、r、l就认为存在一个girl
但这种方法会导致重复统计问题。比如字符串"boyoy":
- 第一个'b'对应一个boy
- 随后的'o'又对应一个boy
- 最后的'y'再对应一个boy
实际上这里应该只统计一个完整的"boy",因为后续的'o'和'y'可能只是同一个boy被部分覆盖的结果。
2.2 进阶思路:贪心匹配与指针跳跃
为了避免重复统计,我们需要实现"贪心匹配"策略:
- 当遇到一个有效字符时(如'b'),立即计数
- 然后尽可能向右匹配该单词的后续字符
- 将指针直接跳到匹配结束的位置
这种策略确保每个单词只被统计一次,即使它的多个字符分散在不同位置。
3. 代码实现细节详解
3.1 主循环结构
代码的核心是一个典型的字符串遍历循环:
c复制for (int i = 0; i < n; ) {
// 处理逻辑
}
注意这里没有在for循环中写i++,因为我们要在内部根据匹配情况手动控制指针移动。
3.2 boy的处理逻辑
当遇到b、o、y时:
c复制if (s[i] == 'b' || s[i] == 'o' || s[i] == 'y') {
boy++;
int j = i + 1;
// 如果是'b',尝试匹配后续的'o'和'y'
i
