KMP算法python实现

参考链接: 浙江大学《数据结构》

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

自编代码展示:

'''
KMP算法的Python实现:
若next[j] = i;表示如下含义:
在模式字符串pattern中,取其子串subString = pattern[0:j+1]
该子串的最大前缀和最大后缀相同,长度为i+1;
即subString[0:i+1] == subString[-i-1:];
并且满足: i<j; 否则当i==j时表示subString[:]==subString[:]无意义
'''



# getNext函数接收一个字符串,返回一个列表,表示next数组


def getNext(pattern):
    length = len(pattern)
    assert length > 0
    next = [None] * length
    for pointer in range(length):
        if pointer == 0:  # 第一个位置取值恒为-1
            next[pointer] = -1
            continue
        else:
            if pattern[pointer] ==  pattern[next[pointer-1]+1]:  # 利用前一个位置的前后缀匹配关系判断下一个字符是否继续得到匹配
                next[pointer] = next[pointer-1] + 1  # 下一个字符仍然匹配,因此长度加1
            else:
                if next[pointer-1] == -1:  # 表示截止到前一个字符,没有前后缀匹配,而且从上一个if语句得知当前字符也未匹配
                    next[pointer] = -1  # 未得到匹配,取值为-1
                    continue  # 继续下一次循环,计算next数组的下一个取值
                scan = next[next[pointer-1]]  # 当前匹配失败后,考虑前一个位置的前后缀匹配关系
                while(True):  
                    if pattern[scan+1] == pattern[pointer]:  # 得到匹配
                        next[pointer] = scan + 1  # 找到匹配的前后缀
                        break  # 跳出while循环
                    else:
                        if scan == -1:  # 表示整个字符串中都未得到匹配,因此取值为-1
                            next[pointer] = -1  # -1表示未得到匹配
                            break
                        else:
                            scan = next[scan]  # 匹配失败,继续前溯
    return next  # 返回next数组



# KMP函数接收一个文本字符串text和一个模式字符串pattern,实现KMP算法
def KMP(text,pattern):  # 返回在文本字符串text中匹配子串的起始位置,若不匹配则返回None
    next = getNext(pattern)  # 获取next数组,列表类型
    length_txt = len(text)  # 获得文本字符串的长度
    length_pat = len(pattern)  # 获得模式字符串的长度
    ptr_txt, ptr_pat = 0, 0  # 初始化两个字符串的指针位置,或者理解为索引位置
    while(ptr_txt<length_txt and ptr_pat<length_pat):  # 循环遍历整个文本字符串
        if pattern[ptr_pat] == text[ptr_txt]:  # 字符获得匹配
            ptr_txt += 1  # 文本字符串的指针加1 
            ptr_pat += 1  # 模式字符串的指针加1
            if ptr_pat == length_pat:  # 判断是否对模式字符串遍历完成
                return (ptr_txt - ptr_pat)  # 获得匹配,返回匹配的起始位置
            continue  # 当前字符串成功匹配,继续进行下一次比较
        else:
            if ptr_pat == 0:  # 模式字符串前溯到起始位置,仍旧未获得匹配的前缀后缀,因此将文本字符串指针向后移动
                ptr_txt += 1  # 文本字符串的指正位置向后移动,继续扫描两个字符串进行比较
            else:
                ptr_pat = next[ptr_pat-1] + 1  # 匹配失败之后前溯
    return None  # 整个文本字符串中都未出现模式字符串,匹配失败,返回未匹配的标志None
            


# pattern = 'abcabcacab'
# pattern = 'abaabcac'
# print('字符串:', pattern)
# print('next数组:', getNext(pattern))

text = input("请输入文本字符串:\t")
pattern = input("请输入模式字符串:\t")
print('您输入的模式字符串是:\t',pattern)
print("获取next数组:",getNext(pattern))
print('您输入的文本字符串是:\t',text)
position = KMP(text,pattern)
print("KMP函数返回结果为:\t",position)
if position == None:
    print("文本字符串\n\t"+text+"\n中未出现模式字符串\n\t"+pattern)
else:
    print("文本字符串\n\t"+text+"\n中出现模式字符串\n\t"+pattern+'\n的位置是:',position)


# text = 'acabaabaabcacaabc'
# pattern = 'abaabcac'

运行结果:

Microsoft Windows [版本 10.0.19044.2075]
(c) Microsoft Corporation。保留所有权利。

C:\Users\chenxuqi>cd /d F:\KMP算法

F:\KMP算法>python testKMP.py
请输入文本字符串:       acabaabaabcacaabc
请输入模式字符串:       abaabcac
您输入的模式字符串是:    abaabcac
获取next数组: [-1, -1, 0, 0, 1, -1, 0, -1]
您输入的文本字符串是:    acabaabaabcacaabc
KMP函数返回结果为:       5
文本字符串
        acabaabaabcacaabc
中出现模式字符串
        abaabcac
的位置是: 5

F:\KMP算法>
F:\KMP算法>

控制台下运行结果图:
在这里插入图片描述

# 本代码使用python语言,实现了KMP字符串匹配算法
NotFound = None

def get_next(pattern):
    i,j = 0,0
    pat_len = len(pattern)
    next = [-1 for k in range(pat_len)]
    for j in range(1,pat_len):
        i = next[j-1]
        while(  (i>=0) and (pattern[i+1]!=pattern[j])  ):
            i = next[i]
        if (pattern[i+1]==pattern[j]):
            next[j] = i+1
        else:
            next[j] = -1
    return next
        
def KMP(string, pattern):
    str_len,pat_len = len(string),len(pattern)
    if str_len<pat_len:
        return NotFound
    next = get_next(pattern)
    ptr_str,ptr_pat = 0,0
    while(ptr_str<str_len and ptr_pat<pat_len):
        if(string[ptr_str]==pattern[ptr_pat]):
            ptr_str += 1
            ptr_pat += 1
        elif (ptr_pat>0):
            ptr_pat = next[ptr_pat-1] + 1
        else:
            ptr_str += 1
    return (ptr_str-ptr_pat if ptr_pat==pat_len else NotFound )

if __name__=='__main__':
    string = input('请输入文本字符串:')
    pattern = input("请输入模式字符串:")
    position = KMP(string, pattern)
    if  position == NotFound:
        print('Not Found.\n')
    else:
        print("所在位置为:", position)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值