KMP算法淺析

KMP算法是一個高效的串匹配算法,常被人戲稱爲‘看毛片算法’,其解決的問題爲:

給定兩個字符串:

t = 'adjfdajfidjfiasidjfosdsfossssfdsd'
p = 'jfidjf'

判定t中是否包含p

首先,我們來看一個樸素的串匹配算法

#coding:utf-8

'''
    樸素的串匹配法
'''
def naive_matching(t,p):
    m, n = len(p), len(t)
    i, j = 0, 0
    while i < m and j < n:
        if p[i] == t[j]:
            i, j = i + 1, j + 1
        else:        #字符不同,則考慮下一個位置
            i, j = 0, j-i+1
    if i == m:       #i==m表示找到匹配,則返回下標。        
        return j-i
    return -1        #無匹配時,返回特殊值



該匹配算法的時間複雜度爲O(n+m),其低效率的原因在於每次把字符看做獨立的操作,完全沒有利用字符串本身的特點。

KMP算法

#coding:utf-8
'''
    KMP看毛片算法:
    1、樸素的匹配算法,其時間複雜度爲O(n*m),KMP的時間複雜度爲O(n+m)
    2、其基本思想爲匹配中不回溯,關鍵點在於匹配失敗時模式串如何前移。
    3、核心點在於定義一個長度爲m的轉移函數pnext,其含義爲一個固定的字符串的最長前綴和最長後綴。
    4、關於最長前綴和最長後綴:
        比如:abcsksabc,那麼這個數組的最長前綴和最長後綴相同必然是abc。
        cbcbc,最長前綴和最長後綴相同是cbc。
        abcbc,最長前綴和最長後綴相同是不存在的。

        **注意最長前綴:是說以第一個字符開始,但是不包含最後一個字符。
        比如aaaa相同的最長前綴和最長後綴是aaa。**
        對於目標字符串ptr,ababaca,長度是7,所以
        pnext[0],pnext[1],pnext[2],pnext[3],pnext[4],pnext[5],pnext[6]分別計算的是
        a,ab,aba,abab,ababa,ababac,ababaca的相同的最長前綴和最長後綴的長度。
        由於a,ab,aba,abab,ababa,ababac,ababaca的相同的最長前綴和最長後綴是
        “”,“”,“a”,“ab”,“aba”,“”,“a”,所以next數組的值是[-1,-1,0,1,2,-1,0],
        這裏-1表示不存在,0表示存在長度爲1,2表示存在長度爲3。這是爲了和代碼相對應。
        比如pnext中某個字符對應的值是4,則在該字符後的下一個字符不匹配時,可以直接移動往前移動ptr 5個長度,再次進行比較判別
'''
#開始構造pnext表函數
def gen_pnext(p):
    i, k, m = 0, -1, len(p)
    pnext = [-1]*m   #初始數組全爲-1
    while i< m-1:    #生成下一個pnext元素
        if k== -1 or p[i] == p[k]:
            i, k = i+1, k+1
            if p[i] == p[k]:
                pnext[i] = pnext[k]
            else:
                pnext[i] = k
        else:
            k = pnext[k]
    return pnext

def matching_KMP(t, p, pnext):
    '''
        毛片算法主程序        
    '''
    j, i = 0, 0
    n, m = len(t), len(p)
    while j < n and i < m:
        if i == -1 or t[j] == p[i]:
            j, i = j+1, i+1
        else:
            i = pnext[i]
    if i == m:
        return j-i
    return -1    #無匹配則返回特殊值


程序運行截圖






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