题目分析
我们需要计算一个由字母 'c' 和 'h' 组成的字符串中所有子串的权值之和,其中权值定义为包含子串 "chhc" 的数量。即我们要统计字符串中所有可能的子串,计算每个子串中 "chhc" 出现的次数,然后将这些权值加总。
问题分解
-
定义问题:
一个子串的权值是它包含
"chhc"子串的次数。 我们的目标是对字符串中所有子串进行遍历,统计每个子串中的"chhc"出现的次数,最后求和。 -
具体步骤:
首先,我们可以通过遍历整个字符串来查找所有
"chhc"子串的位置。 对于每一个"chhc"子串,我们要计算它能构成的子串数量:该子串可以是一个更长子串的一部分,也可以作为一个独立的子串。 -
如何计算子串数量:
对于每一个
"chhc"出现的位置,假设其起始位置为i,它可以出现在从位置0到i的任意起始位置,并且结束位置可以在从i + 4到字符串的末尾的任意位置。因此,左边可以有i + 1种选择,右边可以有n - (i + 4) + 1种选择,其中n是字符串的长度。 -
算法复杂度:
由于我们需要查找字符串中所有
"chhc"子串,并为每个子串计算其能形成的子串数,因此时间复杂度主要取决于我们对字符串的遍历。
解决方案
pythonCopy Code
def solution(s: str) -> int:
count = 0
n = len(s)
# 遍历整个字符串,查找每个 "chhc" 子串
for i in range(n - 3): # 从 i=0 到 i=n-4,保证子串 "chhc" 不会越界
if s[i:i+4] == "chhc": # 如果当前位置是 "chhc"
# 计算以这个 "chhc" 为起始的所有子串的数量
left_choices = i + 1 # 可以从0到i的任意位置
right_choices = n - (i + 4) + 1 # 可以从i+4到n的任意位置
count += left_choices * right_choices # 该 "chhc" 贡献的子串数量
return count
# 测试代码
if __name__ == '__main__':
print(solution("chhchhc") == 8) # 输出 8
print(solution("chhcchhcchhc") == 43) # 输出 43
print(solution("hhhh") == 0) # 输出 0
代码解析
-
初始化计数器:
count = 0:用于累加所有子串的权值之和。 -
遍历字符串:
for i in range(n - 3):遍历每个可能的"chhc"子串的起始位置。i + 4是"chhc"子串的结束位置,因此i只能取到n - 4。 -
匹配子串:
if s[i:i+4] == "chhc":检查当前的四个字符是否是"chhc"。 -
计算子串贡献:
left_choices = i + 1:表示从位置0到位置i的所有可能的起始位置数。right_choices = n - (i + 4) + 1:表示从位置i + 4到位置n-1的所有可能的结束位置数。count += left_choices * right_choices:每个"chhc"对应的子串数量为left_choices * right_choices,我们将其累加到count。 -
返回结果:
最终返回
count,即所有子串的权值之和。
测试用例解析
测试用例 1
输入:s = "chhchhc"
"chhc" 在位置 2 和 4 出现:
- 位置 `2` 贡献了 `3 * 2 = 6` 个子串(左边选择 3 种,右边选择 2 种)。
- 位置 `4` 贡献了 `2 * 2 = 4` 个子串(左边选择 2 种,右边选择 2 种)。
- 总共的权值为
6 + 4 = 8。
测试用例 2
输入:s = "chhcchhcchhc"
"chhc" 在多个位置出现:
- 位置 `0` 贡献了 `1 * 6 = 6` 个子串。
- 位置 `4` 贡献了 `5 * 2 = 10` 个子串。
- 位置 `8` 贡献了 `4 * 1 = 4` 个子串。
- 位置 `12` 贡献了 `3 * 1 = 3` 个子串。
总共的权值为 6 + 10 + 4 + 3 = 43。
测试用例 3
输入:s = "hhhh"
"chhc" 不出现,返回 0。
学习总结
-
字符串匹配与子串计数:
本题涉及了在字符串中查找特定子串,并计算每个子串可以组成的子串数量。通过理解如何计算子串的左边和右边选择的数量,我们可以高效地解决这个问题。
-
优化技巧:
直接遍历字符串,找到每个
"chhc"子串的出现位置,然后根据其位置计算贡献,而不是对每个子串进行暴力检查,可以显著提升效率。 -
学习建议:
练习字符串的遍历、匹配和子串计数问题。这些技巧不仅有助于提高编程能力,还可以帮助你在实际的算法题中快速找到解法。
- 对于类似的问题,可以先思考问题的本质,避免直接暴力遍历所有子串,寻找能够减少计算量的优化方案。
学习计划
-
基础练习:
练习基础的字符串查找、遍历和匹配问题。
-
进阶挑战:
探索更复杂的字符串问题,如字符串的动态规划、滑动窗口等技术。
-
错题反思:
每当遇到难题时,可以分析自己的思路并与其他解法对比,特别是从时间复杂度和空间复杂度的角度进行优化。