问题描述
小M正在研究一个由字母'c'和'h'组成的字符串,他的任务是计算该字符串所有子串中,出现的子串"chhc"的总次数。我们定义一个字符串的权值为其包含"chhc"子串的数量。你的任务是帮助小M求出整个字符串中所有子串的权值之和。
题目解析
题目要求: 给定一个由字母 'c' 和 'h' 组成的字符串,我们需要计算字符串中所有子串中,子串 "chhc" 的出现次数的总和。每个子串的权值定义为它包含 "chhc" 的次数。任务是计算整个字符串所有子串的权值之和。
核心思路:
-
识别
chhc出现的位置: 首先,我们需要在字符串中找出所有"chhc"的出现位置。这是因为每个出现的"chhc"会贡献一些权值。 -
计算每个
"chhc"对所有子串的贡献: 假设我们找到了一个"chhc"出现的位置,记作start,则这个"chhc"对所有包含它的子串贡献一定的权值。对于每一个"chhc",它的贡献取决于它所处的位置以及能够形成的子串的数量。 -
如何计算每个
"chhc"的贡献:- 假设
"chhc"出现的起始位置是start,则该"chhc"形成的子串范围是从start到start + 3(包括)。 - 对于一个子串来说,包含
"chhc"的条件是:该子串的起始位置必须在"chhc"的起始位置start之前或等于start,并且该子串的结束位置必须在"chhc"的结束位置start + 3之后或等于start + 3。
- 假设
-
计算贡献:
left_choices = start + 1表示从字符串的开始到"chhc"起始位置start之间可以选择的子串起始位置的数量(包括start)。right_choices = n - (start + 4) + 1表示从"chhc"结束位置start + 3到字符串末尾之间可以选择的子串结束位置的数量(包括start + 3)。
-
最终的权值计算: 每个
"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
代码步骤详解:
-
初始化:
n = len(s):计算字符串s的长度。count = 0:初始化最终结果变量,用来存储所有子串权值之和。
-
查找所有
"chhc"的位置:positions = []:用于存储所有"chhc"在字符串中的起始位置。for i in range(n - 3):从字符串的开始位置遍历到n - 4(因为"chhc"的长度是 4,不能超出范围)。if s[i:i+4] == "chhc":如果当前位置的子串是"chhc",则记录下该位置i。
-
计算每个
"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中。
-
-
返回结果:
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。
知识点总结
- 子串的选择: 确定每个
"chhc"对所有子串的贡献,实际上是通过选择子串的起始和结束位置来计算的。 - 滑动窗口: 查找
"chhc"的位置时使用了一个简单的滑动窗口方法,滑动窗口大小为 4。 - 组合计数: 每个
"chhc"对子串的贡献是通过选择起始和结束位置的组合数来计算的。