刷题字符串子串权值计算 | 豆包MarsCode AI 刷题

90 阅读4分钟

一、代码分块解析与详细分析


1. 遍历字符串并定位目标子串

功能
遍历字符串,找到所有等于 "chhc" 的子串起始位置。

代码

for i in range(n - target_len + 1):
    # 检查从 i 开始的长度为 target_len 的子串是否等于 "chhc"
    if s[i:i + target_len] == target:
        ...

分析

  • 通过遍历字符串的每一个可能起点,截取长度为 4 的子串并与目标子串比较,判断是否等于 "chhc"
  • 因为目标子串长度固定为 4,循环终点为 n - target_len + 1,防止越界。

感悟
这一部分很基础,但实现过程中容易忽略边界条件,例如当字符串长度小于目标子串时,需要特别注意处理(虽然题目隐含了目标子串存在的可能性)。


2. 计算左侧贡献

功能
计算当前目标子串左侧的起点选择数,即以当前目标子串为右边界的子串数量。

代码

left_contrib = i + 1

分析

  • 假设当前目标子串起始位置是 i,那么左侧可选起点是 [0, 1, 2, ..., i],共计 i + 1 种选择。
  • 这种直接利用索引计算的方法,避免了对每一种可能子串进行显式枚举,提高了效率。

感悟
在很多涉及区间贡献的问题中, “利用索引快速计算” 是一个重要技巧。这里的贡献思想很容易推广到其他场景,比如统计某种特定模式的出现次数或求区间和等。


3. 计算右侧贡献

功能
计算当前目标子串右侧的终点选择数,即以当前目标子串为左边界的子串数量。

代码

right_contrib = n - (i + target_len) + 1

分析

  • 当前目标子串的终点索引为 i + target_len - 1,右侧可选的终点是 [i + target_len, ..., n - 1]
  • 因此可选终点的数量为 n - (i + target_len) + 1

感悟
在实现这一部分时,最关键的就是明确“剩余部分”的范围及其含义。在很多复杂的字符串处理问题中,思路清晰比实现代码更重要。这里的公式实际上是滑动窗口的简化应用。


4. 累加总权值

功能
根据当前目标子串的左侧和右侧贡献,计算其权值并累加到总权值中。

代码

total_weight += left_contrib * right_contrib

分析

  • 当前目标子串对总权值的贡献等于其左侧贡献乘以右侧贡献,即 left_contrib × right_contrib
  • 随着遍历的进行,所有子串的权值都会被正确计算并累加。

感悟
权值的计算公式体现了目标子串对整体的“全局影响”。这一思想在很多优化问题中非常常见,例如动态规划中的“状态转移方程”,或者在数学模型中通过组合思想求总结果。


完整代码汇总

def solution(s: str) -> int:
    n = len(s)  # 字符串长度
    target = "chhc"  # 目标子串
    target_len = len(target)  # 子串长度
    total_weight = 0  # 权值累加器

    # 遍历字符串,寻找 "chhc" 的起始位置
    for i in range(n - target_len + 1):
        # 检查长度为 4 的子串是否为 "chhc"
        if s[i:i + target_len] == target:
            # 左侧贡献:以当前子串为结尾的左侧起点选择数
            left_contrib = i + 1
            # 右侧贡献:以当前子串为起点的右侧终点选择数
            right_contrib = n - (i + target_len) + 1
            # 当前子串的权值
            total_weight += left_contrib * right_contrib

    return total_weight

二、测试结果分析与验证

测试样例

  1. 输入:"chhchhc"

    • 出现 "chhc" 的位置:索引 03
    • 索引 0 贡献:1 × 3 = 3
    • 索引 3 贡献:4 × 1 = 4
      总和:3 + 4 = 8
  2. 输入:"chhcchhcchhc"

    • 出现 "chhc" 的位置:索引 048
    • 索引 0 贡献:1 × 9 = 9
    • 索引 4 贡献:5 × 5 = 25
    • 索引 8 贡献:9 × 1 = 9
      总和:9 + 25 + 9 = 43
  3. 输入:"hhhh"

    • 没有出现 "chhc",权值为 0

三、个人感悟与收获

  1. 贡献值思想的重要性
    本题的核心在于通过“左侧贡献 × 右侧贡献”快速计算出子串的权值,而不是枚举所有可能的子串。这个思想极大地提高了效率,也是一种可复用的模型。
  2. 索引与范围的理解
    在处理字符串问题时,索引的边界和范围决定了解法的正确性。本题对每个子串的边界处理,简洁又高效。
  3. 效率与扩展性
    本题实现了 O(n) 的时间复杂度,相比暴力解法的 O(n^2),效率大幅提升。而且代码逻辑清晰,便于扩展到更复杂的模式匹配问题。
  4. 算法设计的数学美感
    在很多情况下,解决问题的本质是找到“局部到全局”的计算关系。本题中从单个子串到所有子串权值的累加,体现了数学上的抽象与简洁。