📜  门|门 IT 2005 |问题 19(1)

📅  最后修改于: 2023-12-03 15:12:46.380000             🧑  作者: Mango

门|门 IT 2005 |问题 19

本题是门|门 IT 2005考试的第19道问题。

题目描述

给定字符串$s$和$t$,请计算$t$串在$s$串中出现的次数。

输入格式

两行,每行一个字符串。其中,$1 \leq |s| \leq10^5$,$1 \leq |t| \leq10^4$。

输出格式

一个整数,表示$t$在$s$中出现的次数。

样例输入
ababcaba
aba
样例输出
2
解题思路

本题可以使用字符串匹配算法来解决,其中最经典的算法是KMP算法。

KMP算法

KMP算法从目标串(即$t$串)的第一个字符开始匹配,如果在某个位置匹配失败,则通过已经匹配成功的部分信息,判断如何移动目标串的指针位置。

KMP算法的核心思想是:当目标串的子串匹配失败时,利用已经匹配成功的部分信息,计算出匹配指针的最终位置,并将目标串的指针移动到该位置。

我们可以预处理$t$串的next数组,然后使用该数组来进行匹配,从而提高匹配效率。

时间复杂度

KMP算法的时间复杂度为$O(|s|+|t|)$,空间复杂度为$O(|t|)$。

代码实现
def kmp_search(s: str, t: str) -> int:
    """KMP字符串匹配"""
    n = len(t)  # 目标串t的长度
    next = [0] * n  # next数组
    j = 0  # j表示当前匹配成功的字符数,初始值为0
    for i in range(1, n):
        while j > 0 and t[i] != t[j]:
            j = next[j - 1]
        if t[i] == t[j]:
            j += 1
        next[i] = j
    m = len(s)  # 源串s的长度
    j = 0  # j表示当前已经匹配的字符数,初始值为0
    res = 0  # 记录t在s中出现的次数
    for i in range(m):
        while j > 0 and s[i] != t[j]:
            j = next[j - 1]
        if s[i] == t[j]:
            j += 1
        if j == n:  # 匹配成功
            res += 1
            j = next[j - 1]
    return res