Skip to content

猫娘的解题笔记:A. Deletions of Two Adjacent Letters 喵~

哈喽,各位主人,今天由我,你们最爱的小猫娘,来带大家解开一道有趣的算法题哦~ ฅ'ω'ฅ

这道题就像是猫咪在玩一团毛线球,每次抓掉两根线,看看最后能不能剩下我们最喜欢的那一根!是不是听起来就很有趣呢?那么,就请主人备好小鱼干,我们开始吧!


题目大意

我们拿到一个长度为奇数的字符串 s,它只包含小写字母。只要字符串的长度大于1,我们就可以进行一种特殊的操作:选择任意两个相邻的字母,然后把它们删掉!喵~

比如说,如果我们的字符串是 "lemma",我们可以删掉 "le" 得到 "mma",或者删掉 "em" 得到 "lma",等等。每次操作,字符串的长度都会减少2。

现在的问题是,给定一个字符串 s 和一个目标字符 c,我们能不能通过一系列这样的删除操作,最终让字符串 s 只剩下字符 c 呢?

简单来说,就是判断我们能不能把 s 变成 c 啦!


题解方法

一开始看到这个题目,可能会觉得有点复杂,要模拟所有删除的可能吗?那样也太麻烦了喵!本猫娘最讨厌麻烦的事情了。所以,我们得找个聪明的办法!

让我们来分析一下这个操作的特点:

  1. 操作:删除两个相邻的字符。
  2. 长度变化:每次长度减 2。

因为初始字符串 s 的长度是奇数,所以每次减 2,它的长度永远都会是奇数(比如 5 -> 3 -> 1)。最终,我们一定会得到一个长度为 1 的字符串。

那么,问题就变成了:最后剩下的那个字符,可不可能是我们想要的 c 呢?

假设我们想保留字符串 s 中位于第 i 个位置的字符 s[i](这里的 i 是从0开始数的哦),那么我们就必须把它左边的所有字符和右边的所有字符都删掉。

  • s[i] 左边有 i 个字符(从 s[0]s[i-1])。
  • s[i] 右边有 n - 1 - i 个字符(从 s[i+1]s[n-1],其中 n 是字符串总长度)。

为了把一整块连续的字符全部删掉,这块字符的数量必须是偶数!因为我们每次只能删掉2个,奇数个字符是删不完的,总会剩下孤零零的一个,那可不行喵!

所以,要保留 s[i],必须满足两个条件:

  1. 它左边的字符数 i 是偶数。
  2. 它右边的字符数 n - 1 - i 也是偶数。

看起来要判断两个条件?别急,本猫娘有新发现!(✧ω✧) 题目告诉我们,总长度 n 是个奇数。那么 n-1 就一定是个偶数啦!

  • 如果 i 是一个偶数,那么 n - 1 - i 就是 (偶数) - (偶数),结果当然还是偶数
  • 如果 i 是一个奇数,那么 n - 1 - i 就是 (偶数) - (奇数),结果就变成了奇数

所以,只要左边的字符数 i 是偶数,右边的字符数 n - 1 - i 也必然是偶数!我们只需要检查一个条件就够了!

结论就是:我们能最终得到字符 c,当且仅当,在原字符串 s 中,存在一个字符 c,它所在的位置(索引)i 是一个偶数

这下问题是不是变得超级简单了?我们只需要遍历一遍字符串,看看在偶数位置(0, 2, 4, ...)上有没有 c 就行啦!


题解

根据我们刚才的分析,代码实现就非常直接了。就像猫咪悄悄地在字符串上踩点,每隔一个位置检查一下,看看是不是我们想要的那个字母 c 喵~

cpp
#include <iostream>
#include <string>
#include <vector>

void solve() {
    // 先把字符串 s 和目标字符 c 读进来喵
    std::string s;
    std::cin >> s;
    std::string c_str;
    std::cin >> c_str;
    char c = c_str[0];

    bool possible = false;
    int n = s.length();

    // 我们只需要检查所有偶数下标(0, 2, 4, ...)
    // 所以循环的步长是 i += 2
    for (int i = 0; i < n; i += 2) {
        // 如果在偶数位置找到了目标字符 c
        if (s[i] == c) {
            // 那么就说明一定可以做到!
            possible = true;
            // 找到一个就够了,不用再找了,赶紧溜走~
            break;
        }
    }

    // 根据找到的结果,输出 YES 或者 NO
    if (possible) {
        std::cout << "YES\n";
    } else {
        std::cout << "NO\n";
    }
}

int main() {
    // 这是一些让输入输出更快的魔法,喵~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
    
    // 处理多个测试用例
    int t;
    std::cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

知识点介绍

这道题虽然简单,但背后藏着的思想可是很有用的哦!

  1. 奇偶性分析 (Parity Analysis) 这是解决本题的钥匙!在很多算法问题中,特别是那些涉及操作和状态变化的题目,分析某些属性的不变量规律性变化(比如奇偶性、总和等)是一种非常强大的武器。通过抓住“长度永远是奇数”和“删除的块长必须是偶数”这两个核心点,我们把一个复杂的问题转化成了一个简单的判断。

  2. 算法思维:化繁为简 从模拟复杂的删除过程,到发现规律,再到最后只需要一个简单的循环来检查。这个过程就是算法思维的体现——将一个看似棘手的问题,通过逻辑推理,简化成一个容易解决的核心问题。主人以后遇到问题,也要试着像猫咪一样,优雅地找到最简单的解决方法哦!


好啦,这道题就轻松解决啦!主人是不是又变聪明了一点点呢?下次再有难题,也请随时来找我玩耍吧,喵~ ( ´ ω ` )

Released under the MIT License.