编程笔记:字符串 "chhc" 子串权值求和 | 豆包MarsCode AI刷题

70 阅读4分钟

问题描述

小M正在研究一个由字母'c''h'组成的字符串,他的任务是计算该字符串所有子串中,出现的子串"chhc"的总次数。我们定义一个字符串的权值为其包含"chhc"子串的数量。你的任务是帮助小M求出整个字符串中所有子串的权值之和。

题目解析

题目要求: 给定一个由字母 'c''h' 组成的字符串,我们需要计算字符串中所有子串中,子串 "chhc" 的出现次数的总和。每个子串的权值定义为它包含 "chhc" 的次数。任务是计算整个字符串所有子串的权值之和。

核心思路:

  1. 识别 chhc 出现的位置: 首先,我们需要在字符串中找出所有 "chhc" 的出现位置。这是因为每个出现的 "chhc" 会贡献一些权值。

  2. 计算每个 "chhc" 对所有子串的贡献: 假设我们找到了一个 "chhc" 出现的位置,记作 start,则这个 "chhc" 对所有包含它的子串贡献一定的权值。对于每一个 "chhc",它的贡献取决于它所处的位置以及能够形成的子串的数量。

  3. 如何计算每个 "chhc" 的贡献:

    • 假设 "chhc" 出现的起始位置是 start,则该 "chhc" 形成的子串范围是从 start 到 start + 3(包括)。
    • 对于一个子串来说,包含 "chhc" 的条件是:该子串的起始位置必须在 "chhc" 的起始位置 start 之前或等于 start,并且该子串的结束位置必须在 "chhc" 的结束位置 start + 3 之后或等于 start + 3
  4. 计算贡献:

    • left_choices = start + 1 表示从字符串的开始到 "chhc" 起始位置 start 之间可以选择的子串起始位置的数量(包括 start)。
    • right_choices = n - (start + 4) + 1 表示从 "chhc" 结束位置 start + 3 到字符串末尾之间可以选择的子串结束位置的数量(包括 start + 3)。
  5. 最终的权值计算: 每个 "chhc" 的贡献为 left_choices * right_choices,最终的结果是所有 "chhc" 出现位置的贡献总和。

思路总结

  • 第一步:  找到所有 "chhc" 在字符串中的位置。
  • 第二步:  对于每一个找到的 "chhc",计算它对所有包含它的子串的贡献。
  • 第三步:  将所有的贡献累加得到最终结果。

代码详解

def solution(s: str) -> int:
    n = len(s)  # 获取字符串的长度
    count = 0  # 初始化总权值

    # 查找所有"chhc"的起始位置
    positions = []
    for i in range(n - 3):  # 只需要扫描到长度为4的位置
        if s[i:i+4] == "chhc":  # 判断当前子串是否为"chhc"
            positions.append(i)  # 记录该位置

    # 计算每个"chhc"的贡献
    for start in positions:
        left_choices = start + 1  # 从0到start可以选择的起始位置数量
        right_choices = n - (start + 4) + 1  # 从start+4到n可以选择的结束位置数量
        
        # 每个"chhc"贡献的权值为: left_choices * right_choices
        count += left_choices * right_choices
    
    return count

代码步骤详解:

  1. 初始化:

    • n = len(s):计算字符串 s 的长度。
    • count = 0:初始化最终结果变量,用来存储所有子串权值之和。
  2. 查找所有 "chhc" 的位置:

    • positions = []:用于存储所有 "chhc" 在字符串中的起始位置。
    • for i in range(n - 3):从字符串的开始位置遍历到 n - 4(因为 "chhc" 的长度是 4,不能超出范围)。
    • if s[i:i+4] == "chhc":如果当前位置的子串是 "chhc",则记录下该位置 i
  3. 计算每个 "chhc" 的贡献:

    • 对于每个 "chhc" 出现的位置 start,其贡献通过选择子串的起始位置和结束位置来计算:

      • left_choices = start + 1:表示从字符串开头到 "chhc" 起始位置可以选择的子串起始位置的数量。
      • right_choices = n - (start + 4) + 1:表示从 "chhc" 结束位置到字符串末尾可以选择的子串结束位置的数量。
    • count += left_choices * right_choices:每个 "chhc" 的贡献是 left_choices * right_choices,我们将所有的贡献加到 count 中。

  4. 返回结果:

    • return count:返回最终的权值之和。

示例

考虑字符串 "chhchhcchhc"

  • chhc 在字符串中的出现位置有 2 和 8
  • 对于第一个 "chhc"(位置 2),可以选择的子串起始位置为 [0, 1, 2],结束位置为 [6, 7, 8, 9, 10]。所以贡献为 3 * 5 = 15
  • 对于第二个 "chhc"(位置 8),可以选择的子串起始位置为 [0, 1, 2, 3, 4, 5, 6, 7, 8],结束位置为 [10]。所以贡献为 9 * 1 = 9

最终,权值之和为 15 + 9 = 24

知识点总结

  1. 子串的选择: 确定每个 "chhc" 对所有子串的贡献,实际上是通过选择子串的起始和结束位置来计算的。
  2. 滑动窗口: 查找 "chhc" 的位置时使用了一个简单的滑动窗口方法,滑动窗口大小为 4。
  3. 组合计数: 每个 "chhc" 对子串的贡献是通过选择起始和结束位置的组合数来计算的。