首页 > 编程语言 >KMP字符串对比算法及next数组计算

KMP字符串对比算法及next数组计算

时间:2023-09-08 21:13:19浏览次数:43  
标签:数组 son 算法 str KMP 字符串 next

  (注:该贴主要运用python实现该算法)

  先谈谈KMP算法吧。KMP算法的全称是Knuth-Morris-Pratt 算法,它是用来进行字符串查找,即在某个主字符串里面找到某个特定子字符串。但是好像这个问题也可以直接暴力查找来完成啊,可是暴力查找的的缺点是不可忽视的:它的时间复杂度太高了!一旦遇见长的字符串就会让程序运行时间指数型增长。而用KMP算法可以很好的解决代码的时间复杂度高的问题,它的时间复杂度是线性的,也就是说该算法的时间复杂度取决于两个字符串的长度。

 

 

  接下来我会对KMP算法完成任务的大概思路进行叙述

  首先,我们约定一些符号:S为主字符串,也就是被进行查找的字符串;P为子字符串,也就是需要查找的字符串;next为next数组,里面记录了一些解决任务的关键信息,这里先买一些关子,毕竟比较难解释。

  然后就是给定一个主字符串S = ‘ACBACC DBACBACDEA’,子字符串P = ‘ACBACD’,next = [-1, 0, 0, 0, 1, 2]

  接着开始比对

   如上图,当i = 0,j = 0时,二者相等,所以i和j皆进一位;

       当i = 1,j = 1时,二者相等,所以i和j皆进一位;

       当i = 2,j = 2时,二者相等,所以i和j皆进一位;

       当i = 3,j = 3时,二者相等,所以i和j皆进一位;

       当i = 4,j = 4时,二者相等,所以i和j皆进一位;

       当i = 5,j = 5时,二者不相等,所以把j = next[j] = 3,i不变;

(箭头表示当前在比较的位置)

       当i = 5,j = 2时,二者相等,所以i和j皆进一位;

       当i = 6,j = 3时,二者不相等,所以把j = next[j] = 0,i不变;

(箭头表示当前在比较的位置)

       当i = 6,j = 0时,二者不相等,所以把j = next[j] = -1,i不变;

       当i = 6,j = -1时,此时j为特殊值,所以i和j皆进一位;

       当i = 7,j = 0时,二者不相等,所以把j = next[j] = -1,i不变;

       当i = 7,j = -1时,此时j为特殊值,所以i和j皆进一位;

       当i = 8,j = 0时,二者不相等,所以把j = next[j] = -1,i不变;

       当i = 8,j = -1时,此时j为特殊值,所以i和j皆进一位;

(箭头表示当前在比较的位置)

 

       当i = 9,j = 0时,二者相等,所以i和j皆进一位;

       当i = 10,j = 1时,二者相等,所以i和j皆进一位; 

       当i = 11,j = 2时,二者相等,所以i和j皆进一位;

       当i = 12,j = 3时,二者相等,所以i和j皆进一位;

       当i = 13,j = 4时,二者相等,所以i和j皆进一位; 

       当i = 14,j = 5时,二者相等,所以i和j皆进一位;

       当i = 15,j = 6时,此时检测到j>len(P)了,则跳出循环;

       最后返回布尔值,或者返回你想要得到的信息

  如此,我们就走完了一次KMP算法,完成了一次任务,得到了正确的结果

 

  

  通过上面的流程,我们可以得知KMP算法中有一个重要的部分:next数组。

  那next数组是什么呢?next数组主要用于存储j位之前的字符串的最长相同前缀和后缀的长度。

  什么是前缀、后缀呢?"前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。当然,这里指的是在j位之前包括j位的前后缀。

  需要注意的是:假如有一个字符串“abcd”,那么其前缀是:a ab abc,其后缀是:bcd cd d。也就是说前后缀是不止一个的。

  而前文所说的最长相同前缀和后缀的长度即是指:假若有一个字符串“aabab”,其前缀是:a aa aab aaba,其后缀是:aaba aba ba a,那这个的最长相同前后缀是a,所以该位置对应next数组的位置的值的应该是1。

  练习:“abcabx”  [0,0,0,1,2,0]

 )

  这里提供一个代码计算next数组的方法

def get_next(son_str: str) -> list():
    """
    获得next数组

    参数解释 son_str: 需要求next数组的字符串
    返回值: 返回next数组
    """
    length = len(son_str)

    # 定义next数组
    next = length*[None]
    next[0] = -1
    next[1] = 0

    # 计算next数组
    k = -1
    j = 0
    while j < length-1:
        if son_str[k] == son_str[j] or k == -1:
            j += 1
            k += 1
            next[j] = k
        else:
            k = next[k]
    return next

  这里的next[0] = -1主要是因为方便代码处理j回到0时,发现S[i] != P[j]时,i无法进位的情况(用上面第一个方法求出的next数组也可用,但是具体方法得去搜索了,作者是使用的是代码求出来的那个next数组)

 

  到此,该算法也已经讲得差不多了

  下面提供完整的代码

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@文件名     : KMP.py
@描述     :   实现KMP算法,进行字符串比对 
@创建时间     : 2023/09/07/20
@作者     : zrold
@版本     : 1.0
'''


def kmp(farther_str: str, son_str: str) -> bool:
    """
    定义KMP算法, 并根据传进来的两个参数来进行比对, 并返回一个布尔值

    参数解释: farther_str: 进行比对的主字符串, 
              son_str: 子字符串
    返回值: 返回一个布尔值
    """
    # 得到next数组
    next = get_next(son_str)

    # 匹配字符串
    i = 0
    j = 0
    while i < len(farther_str) and j < len(son_str):
        if farther_str[i] == son_str[j] or j == -1:
            i += 1
            j += 1
        else:
            j = next[j]

    if j >= len(son_str):
        return True
    else:
        return False


def get_next(son_str: str) -> list():
    """
    获得next数组

    参数解释 son_str: 需要求next数组的字符串
    返回值: 返回next数组
    """
    length = len(son_str)

    # 定义next数组
    next = length*[None]
    next[0] = -1
    next[1] = 0

    # 计算next数组
    k = -1
    j = 0
    while j < length-1:
        if son_str[k] == son_str[j] or k == -1:
            j += 1
            k += 1
            next[j] = k
        else:
            k = next[k]
    return next


if __name__ == '__main__':
    farther_str = input('请输入需要进行对比的主字符串:')
    son_str = input('请输入需要在主字符串中找到的子字符串:')
    if kmp(farther_str, son_str):
        print(f'确实存在"{son_str}"在"{farther_str}"中')
    else:
        print(f'不存在"{son_str}"在"{farther_str}"中')

 

 

  

 

标签:数组,son,算法,str,KMP,字符串,next
From: https://www.cnblogs.com/zrold/p/17688540.html

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (88)-- 算法导论8.3 1题
    一、用go语言,参照图8-3的方法,说明RADIX-SORT在下列英文单词上的操作过程:COW,DOG,SEA,RUG,ROW,MOB,BOX,TAB,BAR,EAR,TAR,DIG,BIG,TEA,NOW,FOX。文心一言:RADIX-SORT是一种基于字符的排序算法,它将字符串中的每个字符按照其ASCII值进行排序,然后再按照其出现频率进行排序。以下是RADIX-S......
  • 文心一言 VS 讯飞星火 VS chatgpt (88)-- 算法导论8.3 1题
    一、用go语言,参照图8-3的方法,说明RADIX-SORT在下列英文单词上的操作过程:COW,DOG,SEA,RUG,ROW,MOB,BOX,TAB,BAR,EAR,TAR,DIG,BIG,TEA,NOW,FOX。文心一言:RADIX-SORT是一种基于字符的排序算法,它将字符串中的每个字符按照其ASCII值进行排序,然后再按照其出现频率进行排序。以下是RADIX-SORT......
  • 常见的算法时间复杂度
    1.常见的排序算法的平均时间复杂度、最好情况的时间复杂度、最坏情况的时间复杂度、稳定性、是否基于比较的表格 这里,n是要排序的元素数量,k是元素的取值范围。对于基于比较的排序算法,k没有意义,因为这些算法不关心元素的具体值,只关心元素之间的相对顺序。对于非基于比较的排序算......
  • 【回顾】Google Cloud Next '23 引入GKE Enterprise——容器平台的下一阶段发展
    【CloudAce是GoogleCloud全球战略合作伙伴,在亚太地区、欧洲、南北美洲和非洲拥有二十多个办公室。CloudAce在谷歌专业领域认证及专业知识目前排名全球第一位,并连续多次获得GoogleCloud各类奖项。作为谷歌云托管服务商,我们提供谷歌云、谷歌地图、谷歌办公套件、谷歌云认证......
  • 浅析TSINGSEE视频AI智能分析网关车辆检测/车牌识别算法及应用
    在数字化时代,随着大众对出行要求的提升,汽车数量也成与日俱增,为城市与交通管理带来了许多困扰。旭帆科技为给交通管理和车辆安全提供高效的解决方案,特此研发了AI智能车辆检测与车牌识别算法。旭帆科技TSINGSEE青犀视频AI车辆检测、车牌识别算法融合了ORC识别、云计算等多种技术,可将......
  • 视频监控/安防监控/AI视频分析/边缘计算/TSINGSEE青犀AI算法智慧仓储解决方案
    随着全球经济与科学技术的双重推动,我国的仓储管理已经进入了高速发展时期,物流仓储也由简单的储藏仓库向智能化仓储转变。TSINGSEE青犀AI智慧仓储解决方案是利用先进的信息技术和物联网技术来提高仓储管理效率、降低成本的一种仓储管理模式。方案功能1)智能算法TSINGSEE青犀AI算法平......
  • JavaNote04-数组与排序算法
    1.数组的概述1.1数组的概念数组(Array)是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。数组中的概念:数组名、下标(或索引)、元素、数组的长度数组的特点:数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基......
  • Lnton羚通的算法算力云平台关于煤矿安全监管实施方案
    Lnton羚通的算法算力云平台是一款优秀的解决方案,具有突出的特点。它提供高性能、高可靠性、高可扩展性和低成本的特性,使用户能够高效地执行复杂计算任务。此外,平台还提供丰富的算法库和工具,并支持用户上传和部署自定义算法,提升了平台的灵活性和个性化能力。煤矿监管电子封条算法是......
  • 智慧能源方案:TSINGSEE青犀AI算法中台在能源行业的应用
    一、方案背景互联网、物联网、人工智能等新一代信息技术引领新一轮产业革命,加快能源革命步伐。尤其是随着人工智能技术的不断发展,AI智能检测与识别技术在能源行业的应用也越来越广泛。与此同时,国家出台多项政策,将智慧能源纳入新基建融合基础设施等,这些因素都加快了能源智慧互联网的......
  • 视频监控/安防监控/AI视频分析/边缘计算/TSINGSEE青犀AI算法智慧仓储解决方案
    随着全球经济与科学技术的双重推动,我国的仓储管理已经进入了高速发展时期,物流仓储也由简单的储藏仓库向智能化仓储转变。TSINGSEE青犀AI智慧仓储解决方案是利用先进的信息技术和物联网技术来提高仓储管理效率、降低成本的一种仓储管理模式。方案功能1)智能算法TSINGSEE青犀A......