python数据结构之KMP算法的实现

版权声明:本文为博主原创文章,未经博主允许可以转载。 https://blog.csdn.net/killeri/article/details/82979183

我相信网上已经有很多关于KMP算法的讲解,大致都是关于部分匹配表的实现思路和作用,还有就是目标串的下标不变,仅改变模式串的下标来进行匹配,确实用KMP算法,当目标串很大模式串很小时,其效率很高的,但都是相对而言。至于对于部分匹配表的作用以及实现思路,建议看一下这篇文章写的是比较易懂的,英文看不懂?那你就看别的国人写的吧,其实大概都差不多,我这里主要是用python语言实现一个部分匹配表以及实现KMP算法
首先是对于部分匹配表的实现,它的实现其实有两种,一种是对目标串的所有子串的部分匹配值都计算出来放在一个数组里面,想使用的时候之间通过下标取用就可以了,但我使用的是另外一种,实时计算子字符串的部分匹配值,也就是说,定义一个函数,当传进一个字符串时就返回一个其部分匹配值。其实这个函数就是一个核心,如果搞懂了这个函数,你想计算出全部的部分匹配值不是很简单吗?话不多说,我们贴出来代码:

# 函数用于求一个匹配子串的部分匹配值
def partialMatchTable(string):
    length = len(string)
    # 已经匹配的模式串的长度
    x = 1 # 用于表示前缀后缀的长度,始终小于串长度
    stringMatchValues = []
    # 用于存放模式串的可能匹配值
    while x < length:
        if string[:x] == string[-x:]:
            # 如果前缀和后缀相等,那么,这就是一个可能的部分匹配值
            stringMatchValues.append(len(string[:x]))
            x += 1
        x += 1
    if not stringMatchValues:
        return 0
    # 如果没有部分匹配值,则返回0
    return max(stringMatchValues)


以上函数比较简单,就是比较而已,关键在于切片的获取。这样,你穿进去一个string,函数就返回一个它的部分匹配值。

重点在于KMP算法的实现,实现代码如下:

import time
from 部分匹配表 import *

starTime = time.time()
def KMP_algorithm(t, p):
    lens = 0 # lens是已经匹配的串的长度
    tIndex, pIndex = 0, 0
    # 目标串和模式串的下标
    m, n = len(p), len(t)
    # m, n是模式串和目标串的长度
    while pIndex < m and len(t[tIndex:]) >= m-1:
        # 只有当p的下标小于m,而且t的剩余的长度大于或者等于p的长度
        if p[pIndex] == t[tIndex]:
            pIndex +=1
            tIndex += 1
            # 如果两个的相应下标的值相等,那么接着比较下一个
        else:
        # 如果不相等
            string = p[:pIndex]
            # 这里取出已匹配模式串
            if string == '':
            # 没有已经匹配的模式串
                tIndex += 1
                pIndex = 0
            else:
            # 如果有已经匹配的模式串,我们知道目标字符串的下标是不变的,改变的只有
            # 模式字符串的下标
                pIndex = partialMatchTable(string)
    if pIndex == m:
        return (tIndex - m)
    print(len(t[tIndex:]))
    return ("不匹配")

t = open("目标串.txt", "r")
# 去掉字符串之间的空格
for i in t.readlines():
    print(i.rstrip(), sep="", end="", file=open("目标串2.txt", "a"))
T = open("目标串2.txt", "r").read()

y = KMP_algorithm(T, "18117601")
print(y)
endTime = time.time()
print(starTime-endTime, end="运行时间")


代码中各个变量表示什么已经讲的很清楚了,其中一段对于文件的操作,是去除文件中的所有空格。

代码中的注释已经讲所有可能有困惑的地方都讲清楚了,看的时候最后结合你图看,上面链接里面就有可能需要的图解。嗯

差不多就是这样,KMP算法我可是研究了很长的时间才写出来的。接下来我来讲一下原理。
首先什么是回溯?:
哈哈哈,就是目标串和模式串已经比较过的部分,如果在下一次比较中再进行比较那么就是叫回溯,而KMP算法成功的避免了回溯,至于怎么避免的,我来用草稿纸画一张图,客官们凑合着看。
在这里插入图片描述

其实图片已经能说明所有问题了! 就这样,完, 不对,还有一种字符串匹配算法–Boyer-Moore算法,它的效率可能比KMP算法还要高很多,嗯,有兴趣的可以关注一下,因为下一篇我想讲讲这个算法。

猜你喜欢

转载自blog.csdn.net/killeri/article/details/82979183