📌  相关文章
📜  门| Sudo GATE 2020 Mock II(2019 年 1 月 10 日)|第 36 题(1)

📅  最后修改于: 2023-12-03 14:58:33.805000             🧑  作者: Mango

门| Sudo GATE 2020 Mock II(2019 年 1 月 10 日)|第 36 题

本题是由 Sudo GATE 2020 Mock II(2019 年 1 月 10 日)|第 36 题 修改而来。本文将对该题进行详细解析。

题目描述

门是一个由 0 和 1 组成的串。我们称门“好”如果它只由 0 和 1 组成且不存在 011 的子串(即,它的子串中不会有 011 这个形式的子串)。给定一个门的字符串 s,计算 s 中有多少个长为 k 的“好”子串。

例如,如果 s = "1010011010" 和 k = 3,则 s 中“好”的子串是 “101”,“010”,“001”,“110”,“101” 和 “010”。所以答案为 6。

输入格式

输入包含一个门的字符串 s、一个字符串长度 k,1 ≤ |s| ≤ 10^5,1 ≤ k ≤ 100。

输出格式

输出 s 中“好”的子串的数量。

解题思路

本题是一个纯粹的字符串处理问题。首先,我们需要遍历 s 中所有长度为 k 的子串,看它们是否“好”;其次,我们需要找到一个高效的算法来检测是否存在子串 011。

对于长度为 k 的子串,我们有两种思路。第一种是将长度为 k 的子串都存到一个数组里,然后直接判断它们是否“好”。这种方法的空间复杂度是 O(n),其中 n 是字符串 s 的长度。第二种方法是维护一个长度为 k 的滑动窗口,窗口每次向右移动一个字符。因此,不需要开辟额外的空间来存储子串。最后,我们只需要统计计数器即可。这种方法的空间复杂度是 O(1)。

接下来,我们需要判断一个子串是否“好”。显然,如果一个子串不仅仅由 0 和 1 组成,那么它肯定不是“好”的子串。因此,如果一个子串中有非 0 和 1 的字符,我们可以直接跳过不做处理。如果所有字符都是 0 或 1,则需要进一步判断是否存在 011 子串。

为了检测是否存在 011 子串,我们可以遍历整个子串,检查相邻的三个字符是否匹配“011”的模式。如果找到了一个“011”的子串,直接跳出循环并返回 false。如果整个子串扫描完毕也没有发现“011”,则返回 true。这种方法指针只需要从头到尾扫描一遍,时间复杂度为 O(n)。

综上所述,我们可以采用滑动窗口的方法在 O(n) 的时间复杂度内解决该问题。

代码实现

下面是 Python3 代码实现,以滑动窗口的方式处理“好”的子串。

def count_good_substring(s: str, k: int) -> int:
    n = len(s)
    cnt = 0
    for i in range(n - k + 1):
        # 判断子串是否“好”
        if is_good(s[i:i + k]):
            cnt += 1
    return cnt

def is_good(sub: str) -> bool:
    for i in range(len(sub)):
        # 判断该子串是否由 0 和 1 组成
        if sub[i] != "0" and sub[i] != "1":
            return False
        if i >= 2 and sub[i - 2:i + 1] == "011":
            return False
    return True
总结

本题是一道较为简单的字符串处理题,主要考察了对字符串的扫描和判断能力。学会滑动窗口的使用方法可以大大提高代码效率,同时,也能够使思路更加清晰明了。