KMP算法-python实现

kmp算法思想

两个字符串匹配,kmp算法时间复杂度O(m+n)。总体思想就是对于匹配子串,利用先验知识尽可能的不重复匹配。

next数组的定义

对于子串,计算出当前字符之前字符串中相同字符的个数,这样在子串和字符串当前字符匹配不成功时,就可以直接跳转到之前字符串相同的位置的下一个,减少了匹配的次数。
例如:abab,next数组为[0,0,0,1],表示当前字符匹配不成功时,前面字符串包含的相同子串的长度,最后一个b,前面的子串为aba,包含相同子串为a,个数为2,需要跳转到下标为1的位置,所以next值为1;
进一步优化next,解决aaaab这种特殊情况,原始next数组为:[0, 0, 1, 2, 3],可以看到aaaa为连续相同字符,即使按照next数组进行了跳转,跳转后的字符和当前字符是相同的,这是没有意义的,为了解决这一 问题,就需要对next数组进行优化,得到[0, 0, 0, 0, 3],当跳转后的字符与当前字符相同时,就继续进行跳转,直到跳转后的字符与当前字符不同,或者到字符串最开始0位置。

构建好next数组后,就可以将字符串与子串进行匹配操作。字符串从头到尾遍历,如果遍历的当前字符与子串相同,就继续,如果不同,则子串查询next数组,跳转到next中的位置,继续遍历比较。

def data_next(str_data):
    tmp_data = str_data
    i = 1
    j = 0
    data_next = [0]
    # 求字符串中前缀和后缀相同的个数
    while i < len(str_data):
        if str_data[i] == tmp_data[j]:
            i += 1
            j += 1
            data_next.append(j)
        else:
            j = 0
            if str_data[i] == tmp_data[j]:
                data_next.append(1)
            else:
                data_next.append(0)
            i += 1
    # next数组整体右移一位,当前数组表示字符不匹配是跳转的字符串下标
    data_next = [0] + data_next[:-1]
    print("原始next数组:"+str(data_next))
    # next数组优化,当next数组中的跳转字符与当前字符相同时,需要继续跳转,知道跳转后字符与当前字符不同为止或者调到最开始
    for index in range(len(data_next)):
        index_str = str_data[index]
        next_new = data_next[index]
        while str_data[next_new] == index_str and next_new != 0:
            next_new = data_next[next_new]
        data_next[index] = next_new
    print("优化后next数组:"+str(data_next))
    return data_next


def data_match(data_1, data_2, data_next):
    j = 0
    for i in data_1:
        if j == len(data_2)-1:
            return True
        elif i == data_2[j]:
            j += 1
        else:
            j = data_next[j]
    return False

if __name__ == '__main__':
    ss = 'ababaaababaa'
    ll = 'aaaab'
    next = data_next(ll)
    print(data_match(ss, ll, next))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值