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    #无匹配则返回特殊值


程序运行截图






猜你喜欢

转载自blog.csdn.net/topkipa/article/details/79206520