
题目考点
这道题主要考:
- 字符串遍历
len()获取字符串长度for循环和range()- 字符串切片
- 条件判断
if - 计数器变量
count
这题的核心不是简单使用 string.count(sub_string),因为这个题目要求从左到右逐个位置检查,通常要允许重叠匹配。
例如:
ABCDCDC
CDC
CDC 出现了两次:
ABCDCDC
CDC
CDC
所以答案是 2。
审题
题目输入两行:
第一行是原字符串:
ABCDCDC
第二行是要查找的子字符串:
CDC
题目要求输出:子字符串在原字符串中出现的次数。
需要注意两个点。
第一,大小写敏感。比如:
abc
ABC
这两个不一样。
第二,要从左到右检查每一个可能的位置,而不是只找不重叠的部分。
思路提示
你可以把这道题想成“拿一个小窗口在大字符串上从左往右滑动”。
假设:
string = "ABCDCDC"
sub_string = "CDC"
sub_string 的长度是 3,所以我们每次都从原字符串里截取长度为 3 的一段,看看它是不是 "CDC"。
从左到右检查:
i = 0 取 string[0:3] 得到 "ABC"
i = 1 取 string[1:4] 得到 "BCD"
i = 2 取 string[2:5] 得到 "CDC" 匹配,count + 1
i = 3 取 string[3:6] 得到 "DCD"
i = 4 取 string[4:7] 得到 "CDC" 匹配,count + 1
最后 count = 2。
完整设计思路
第一步:先拿到两个字符串的长度
我们需要知道:
len(string)
len(sub_string)
例如:
len("ABCDCDC") = 7
len("CDC") = 3
第二步:确定循环范围
因为每次要取长度为 3 的小片段,所以最后一个起点不能超过 4。
如果从 i = 5 开始取:
string[5:8]
就不够 3 个字符了。
所以循环范围应该是:
range(0, len(string) - len(sub_string) + 1)
为什么要 + 1?
因为 range() 的右边界取不到。
例如:
range(0, 5)
实际得到的是:
0, 1, 2, 3, 4
对于样例:
len(string) = 7
len(sub_string) = 3
所以:
len(string) - len(sub_string) + 1
= 7 - 3 + 1
= 5
循环就是:
range(0, 5)
实际检查的位置是:
0, 1, 2, 3, 4
刚好够用。
第三步:每次截取一段字符串
用切片:
string[i : i + len(sub_string)]
如果这段等于 sub_string,说明找到一次。
第四步:用计数器记录次数
一开始:
count = 0
每找到一次:
count += 1
最后返回 count。
代码实现
按照 HackerRank 这类题目的模板,可以这样写:
def count_substring(string, sub_string):
count = 0
sub_len = len(sub_string)
for i in range(0, len(string) - sub_len + 1):
current_part = string[i:i + sub_len]
if current_part == sub_string:
count += 1
return count
if __name__ == '__main__':
string = input().strip()
sub_string = input().strip()
count = count_substring(string, sub_string)
print(count)
这里的模板:
if __name__ == '__main__':
可以先理解成:程序从这里开始正式读取输入并执行。
这一段:
string = input().strip()
sub_string = input().strip()
意思是读取两行输入,并去掉首尾空白。
运行演示
输入:
ABCDCDC
CDC
程序中:
string = "ABCDCDC"
sub_string = "CDC"
sub_len = 3
count = 0
循环过程:
| i | 截取内容 | 是否等于 CDC | count |
|---|---|---|---|
| 0 | ABC | 否 | 0 |
| 1 | BCD | 否 | 0 |
| 2 | CDC | 是 | 1 |
| 3 | DCD | 否 | 1 |
| 4 | CDC | 是 | 2 |
最终输出:
2
方法总结
这一类题以后可以这样想:
看到“统计子字符串出现次数”,不要急着用现成函数。先问自己:
- 子字符串能不能重叠?
- 是否大小写敏感?
- 是否要求从左到右逐个位置检查?
- 每次应该截取多长的一段?
如果允许重叠,就用“滑动窗口”的思路:
for i in range(0, len(string) - len(sub_string) + 1):
判断 string[i:i + len(sub_string)] 是否等于 sub_string
这是字符串匹配题里非常常见的入门写法。
练习
请你自己试一题:
输入:
aaaa
aa
请问子字符串 "aa" 出现了几次?
提示:不要只看不重叠的情况,要从每一个位置开始检查。
起点分别是 0、1、2。



