(注:该贴主要运用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}"中')

  

KMP字符串对比算法及next数组计算的更多相关文章

  1. 字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串

    Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...

  2. KMP字符串查找算法

    #include <iostream> #include <windows.h> using namespace std; void get_next(char *str,in ...

  3. 字符串类——KMP子串查找算法

    1, 如何在目标字符串 s 中,查找是否存在子串 p(本文代码已集成到字符串类——字符串类的创建(上)中,这里讲述KMP实现原理) ? 1,朴素算法: 2,朴素解法的问题: 1,问题:有时候右移一位是 ...

  4. poj 2406:Power Strings(KMP算法,next[]数组的理解)

    Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 30069   Accepted: 12553 D ...

  5. 字符串匹配KMP算法中Next[]数组和Nextval[]数组求法

    数据结构课本上给了这么一段算法求nextval9[]数组 int get_nextval(SString T,int &nextval[ ]) { //求模式串T的next函数修正值并存入数组 ...

  6. KMP算法的next[]数组通俗解释

    原文:https://blog.csdn.net/yearn520/article/details/6729426 我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以 ...

  7. hdu 1358:Period(KMP算法,next[]数组的使用)

    Period Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. KMP 算法 & 字符串查找算法

    KMP算法 Knuth–Morris–Pratt algorithm 克努斯-莫里斯-普拉特 算法 algorithm kmp_search: input: an array of character ...

  9. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  10. KMP字符串模式匹配详解(转)

    来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...

随机推荐

  1. Python基础 - 运算符优先级

    以下表格列出了从最高到最低优先级的所有运算符: 运算符 描述 ** 指数 (最高优先级) ~ + - 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) * / % // 乘,除,取模 ...

  2. 一个.Net强大的Excel控件,支持WinForm、WPF、Android【强烈推荐】

    推荐一个强大的电子表单控件,使用简单且功能强大. 项目简介 这是一个开源的表格控制组件,支持Winform.WPF和Android平台,可以方便的加载.修改和导出Excel文件,支持数据格式.大纲.公 ...

  3. 10 款 VS Code 插件神器,第 7 款超级实用!

    VS Code 是这两年非常热门的一款 IDE,它不仅有提升开发体验的界面.轻量化的编辑器,还有丰富而强大的插件,这些优秀的插件使得 VS Code 生态体系更加吸引人,让开发效率大大提升.本文来介绍 ...

  4. 「AntV」L7地理可视化:从入门到实践

    1. 前言 这是一篇由浅入深的AntV L7的学习笔记总结,记述了从了解到使用的一些过程 本文所使用的数据(包括数据处理过程)和代码均有详细描述,所有案例均可复现,甚至大部分代码可直接使用 如果喜欢分 ...

  5. C#.NET CORE .NET6 RSA 私钥签名 公钥验签(验证签名) ver:20230614

    C#.NET CORE .NET6 RSA 私钥签名 公钥验签(验证签名) ver:20230614 环境说明: .NET CORE 版本:.NET 6 . .NET CORE 对于RSA的支持: 1 ...

  6. Python潮流周刊#7:我讨厌用 asyncio

    你好,我是猫哥.这里记录每周值得分享的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 首发于我的博客:https://pyt ...

  7. 从输入URI到浏览器渲染中间都经历了什么

    这篇文章总共分为两个部分,第一部分我会把从输入url到浏览器渲染的整个流程给大致说一下.第二部分我就会一一介绍各个部分的详细作用. 一.从输入url到浏览器渲染的整个流程   1.DNS域名解析 2. ...

  8. XTTS系列之三:中转空间的选择和优化

    通常选择XTTS做迁移的数据库都不会太小的,至少都是几T.几十T这样的规模,这种级别的数据量原有空间不够用,所以在迁移过程临时用作存放迁移数据库备份文件的空间也是需要提前考虑规划的问题. 最近就有客户 ...

  9. Spring Loaded代码热更新实践和原理分析

    1.引言 开发者在编码效率和快速迭代中的痛点场景包括: 修改代码后,需要频繁重启应用,导致开发效率低下: 实时调试时,不能立即看到代码修改的结果: 大型项目中,重启的时间成本较高. 针对这些问题,本文 ...

  10. CSS border(边框)

    CSS 边框属性 CSS边框属性允许你指定一个元素边框的样式和颜色. 可以为上下左右每个框 定制不同的样式和颜色. 边框样式 边框样式属性指定要显示什么样的边界. border-style属性用来定义 ...