Python中的BF与KMP算法

BF(暴力匹配)算法

BF算法是一种简单的字符串匹配算法,其基本思想是:

  1. 从主字符串的第一个字符开始,逐个字符与子字符串进行比较。
  2. 如果当前字符匹配成功,则继续比较下一个字符。
  3. 如果当前字符匹配失败,则将主字符串的起始位置向后移动一位,重新开始比较。
  4. 重复上述过程,直到找到匹配的子字符串或遍历完主字符串。

优点:

  • 实现简单,易于理解。

缺点:

  • 时间复杂度较高,这种算法的时间复杂度为 O((n-m+1) * m),在最坏情况下效率较低,但实现简单,适用于小规模的字符串匹配任务。

代码示例

def bf_search(text, pattern):
    n = len(text)
    m = len(pattern)
    for i in range(n - m + 1):
            #range(n - m + 1) 确保了即使 pattern 刚好在 text 的末尾,也能进行匹配检查。
        j = 0  
        #变量 j 用于跟踪当前比较的字符位置。
        while j < m and text[i + j] == pattern[j]:
                        #text[i + j] 表示文本中从位置 i 开始的第 j 个字符,而 pattern[j] 表示模式中的第 j 个字符。通过比较这两个字符,算法逐个字符地检查模式是否与文本中的某个子字符串匹配。
            j += 1
        if j == m:
            return i
        #如果 j 达到 m,意味着 pattern 的所有字符都成功匹配,此时返回当前的起始索引 i。
    return -1
    #如果外层循环结束后仍未找到匹配,则返回 -1,表示 text 中不存在 pattern。

# 测试
text = "abxabcabcaby"
pattern = "abcaby"
print("BF算法匹配结果:", bf_search(text, pattern))

#运行结果
BF算法匹配结果: 6

KMP(Knuth-Morris-Pratt)算法

KMP算法是一种改进的字符串匹配算法,其基本思想是:

  1. 通过预处理子字符串,构建部分匹配表(LPS数组),记录子字符串的前缀和后缀的最长公共部分。
  2. 在匹配过程中,利用部分匹配表,避免重复比较,从而提高匹配效率。

步骤:

  1. 计算子字符串的部分匹配表(LPS数组)。
  2. 使用部分匹配表进行字符串匹配,避免重复比较。

优点:

  • 时间复杂度较低,最坏情况下为O(n+m),其中n是主字符串的长度,m是子字符串的长度。

缺点:

  • 实现相对复杂,需要预处理子字符串。

代码示例

def compute_lps(pattern):
    m = len(pattern)
    lps = [0] * m
    #初始化一个长度为 m 的 LPS 数组,所有元素初始值为 0。
    length = 0
    #初始化一个长度为 m 的 LPS 数组,所有元素初始值为 0。
    i = 1
    #i = 1 表示从模式字符串 pattern 的第二个字符开始。这是因为第一个字符的 LPS 值总是 0,没有前缀和后缀可以匹配。
    while i < m:
        if pattern[i] == pattern[length]:
            length += 1
            lps[i] = length
            i += 1
        else:
            if length != 0:
                length = lps[length - 1]#这一步骤避免了重新计算已经匹配的前缀。
            else:
                lps[i] = 0
                i += 1
    return lps

def kmp_search(text, pattern):
    n = len(text)
    m = len(pattern)
    lps = compute_lps(pattern)
    #函数通过调用compute_lps函数计算模式字符串的最长前缀后缀(LPS)数组。LPS数组用于在模式匹配过程中跳过不必要的字符比较,从而提高搜索效率。
    i = 0
    j = 0
    while i < n:
        if pattern[j] == text[i]:#检查当前模式字符串的字符pattern[j]是否与文本字符串的字符text[i]匹配。
            i += 1
            j += 1
        if j == m:#表示模式字符串已经完全匹配,此时返回匹配的起始索引i - j
            return i - j
        #这两个if语句是独立的,意味着即使第一个if语句的条件不满足,代码仍然会检查第二个if语句的条件。这种结构允许在字符匹配时更新索引,并在模式字符串完全匹配时立即返回匹配的起始位置。
        elif i < n and pattern[j] != text[i]:
            if j != 0:
                j = lps[j - 1]
            else:
                i += 1
    return -1
# 测试
text = "abxabcabcaby"
pattern = "abcaby"
print("KMP算法匹配结果:", kmp_search(text, pattern))
#运行结果
KMP算法匹配结果: 6

总结

  1. bf_search(text, pattern):

    • 实现了暴力搜索算法。
    • 遍历 text 中的每一个子字符串,逐字符比较 pattern
    • 如果找到匹配的子字符串,返回其起始索引;否则返回 -1。
  2. compute_lps(pattern):

    • 计算模式字符串的最长前缀后缀(LPS)数组。
    • LPS 数组用于在 KMP 算法中跳过不必要的字符比较,从而提高搜索效率。
  3. kmp_search(text, pattern):

    • 实现了 KMP 字符串匹配算法。
    • 使用 compute_lps 函数计算模式字符串的 LPS 数组。
    • 通过 LPS 数组在模式匹配过程中跳过不必要的字符比较。
    • 如果找到匹配的子字符串,返回其起始索引;否则返回 -1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值