current_part = string[i:i + sub_len]

题目考点

这道题主要考:

  1. 字符串遍历
  2. len() 获取字符串长度
  3. for 循环和 range()
  4. 字符串切片
  5. 条件判断 if
  6. 计数器变量 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截取内容是否等于 CDCcount
0ABC0
1BCD0
2CDC1
3DCD1
4CDC2

最终输出:

2

方法总结

这一类题以后可以这样想:

看到“统计子字符串出现次数”,不要急着用现成函数。先问自己:

  1. 子字符串能不能重叠?
  2. 是否大小写敏感?
  3. 是否要求从左到右逐个位置检查?
  4. 每次应该截取多长的一段?

如果允许重叠,就用“滑动窗口”的思路:

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

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇