Python实现KMP字符串查找算法

KMP算法的实现

        通过观看b站的视频https://www.bilibili.com/video/av49930100?from=search&seid=12267121724301893524之后没事做就用python来实现KMP算法。

精简代码

# 取字符串中最大相等的前后缀长度
def prefixSuffix(str = ""):
    maxIndex, i = len(str) - 1, 0
    while i < maxIndex:
        if str[:maxIndex - i] == str[i + 1:]:
            return maxIndex - i
        i += 1
    return 0
# 取模式串的next数组保存到列表
def getNext(str = ""):
    l, i, next = len(str), 0,[]
    while i < l:
        next.append(prefixSuffix(str[:i]))
        i += 1
    return next
# 字符串查找函数
def find(str1 = "", str2 = "", i = 0):
    str1Len, str2Len, next, nextIndex = len(str1), len(str2), getNext(str2), 0
    while nextIndex < str2Len:
        if str1Len - i < str2Len - nextIndex:
            return -1
        if str1[i] == str2[nextIndex]:
            i += 1
            nextIndex += 1
        else:
            if nextIndex == 0:
                i += 1
            nextIndex = next[nextIndex]
    return i - str2Le

注释的代码

# 取字符串中最大相等的前后缀长度,先从字符串自身长度-1开始判断而不是从长度最小开始,比较简单
# 如果从长度最小开始判断情况会后很多比较复杂
def prefixSuffix(str = ""):
    maxIndex, i = len(str) - 1, 0
    while i < maxIndex:
        if str[:maxIndex - i] == str[i + 1:]:
            return maxIndex - i
        i += 1
    return 0

# 取模式串的next数组保存到列表
def getNext(str = ""):
    l, i, next = len(str), 0,[]
    while i < l:
        next.append(prefixSuffix(str[:i]))
        i += 1
    return next

# 字符串查找函数,
# 第一个参数是被查找的字符串,
# 第二个参数是要查找的字符串,
# 第三个参数是在哪个位置开始查找默认从下标0开始查找
# 返回值是查找的字符串在主串中从startInsex开始的第一次出现的第一个字符的下标
# 没有找到返回-1
def find(str1 = "", str2 = "", i = 0):
    str1Len, str2Len, next, nextIndex = len(str1), len(str2), getNext(str2), 0
    # 根据MKP算出的next下标进行对比
    while nextIndex < str2Len:
        # 如果str1剩下的字符串比str2剩下的字符串少,说明没有判断下去的必要了
        if str1Len - i < str2Len - nextIndex:
            return -1
        if str1[i] == str2[nextIndex]: # 如果当前字符相等则主串下标i和模式串下标nextIndex各加1
            i += 1
            nextIndex += 1
        else:
            if nextIndex == 0: # 如果模式串中对比的字符是第一个并且和主串的字符对比失败则,继续和主串的下一个字符进行对比
                i += 1 # 指向主串的下一个字符
            nextIndex = next[nextIndex] # 模式串后移
    return i - str2Len

if __name__=="__main__":
    print(find('ABABABAABABAAABABAA123ABABAAABABAA123', 'ABABAAABABAA',8))
    print(find('0123456789abcdef', 'b'))
    print(find('''KMP算法:字符串的模式匹配是对字符串的基本操作之一,广泛应用于生物信息学、信息检索、拼写检查、语言翻译、数据压缩、网络入侵检测等领域,
如何简化其复杂性一直是算法研究中的经典问题。字符串的模式匹配实质上就是寻找模式串P是否在主串T 中,且其出现的位置。
我们对字符串匹配的效率的要求越来越高, 应不断地改良模式匹配算法,减少其时间复杂度。
    KMP算法是由D.E. Knuth、J.H.Morris和V.R. Pratt提出的,可在一个主文本字符串S内查找一个词W的出现位置。
此算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新检查先前匹配的字符。
这个算法是由高德纳和沃恩·普拉特在1974年构思,同年詹姆斯·H·莫里斯也独立地设计出该算法,最终由三人于1977年联合发表。
该算法减少了BF算法中i回溯所进行的无谓操作,极大地提高了字符串匹配算法的效率。
''', '1977'))

你可能感兴趣的:(Python实现KMP字符串查找算法)