python數據結構之KMP算法的實現

我相信網上已經有很多關於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算法還要高很多,嗯,有興趣的可以關注一下,因爲下一篇我想講講這個算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章