一、什么是 KMP 算法

KMP 算法是一种改进的字符串匹配算法,用于判断一个字符串是否是另一个字符串的子串

二、KMP 算法的时间复杂度

O(m+n)

三、Next 数组 - KMP 算法的核心

KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 next() 实现

1、next 数组

长度与字符串长度一致,每个位置存储对应字符的最长匹配长度

2、next 数组通过遍历子字符串中"前缀"和"后缀"的最长的共有元素的长度来获得

例如 ABCDABD,得到的 next 数组为 [0,0,0,0,1,2,0]

简单地观察一下就会发现,该算法会进行最少 21 次的字符串判断,这还是在不考虑字符串匹配的时间消耗,光此一项的时间复杂度就是

O(n) = (n(n - 1)) /2 = n² / 2 + n / 2 = n²

在加上匹配字符串,就是m + n²显然大于KMP算法的时间复杂度m + n

3、next数组通过加入回溯法,在遍历子字符串时,判断逐步判断字符是否相同

function get_next(s) {
var i = 1;
var j = 0;
var next = [0];
while (i < s.length) {
if (j == 0 || s.charAt(i - 1) == s.charAt(j - 1)) {
i++;
j++;
next.push(j);
} else {
j = next[j - 1];
}
}
return next;
}

例如:

j=0,    i=1,    (j=0),     next=[0,1];
j=1, i=2, (A!=B), j=next[0];
j=0, i=2, (j=0), next=[0,1,1];
j=1, i=3, (A!=C), j=next[0];
j=0, i=3, (j=0), next=[0,1,1,1];
j=1, i=4, (A!=D), j=next[0];
j=0, i=4, (j=0), next=[0,1,1,1,1];
j=1, i=5, (A=A), next=[0,1,1,1,1,2];
j=2, i=6, (B=B), next=[0,1,1,1,1,2,3];

总共运行9次就获得了next数组,算法时间复杂度是O(n) = n

4、对于两个next数组的用法也有区别

//1.阮
//i值即移动位数:移动位数 = 已匹配的字符数 - 对应的部分匹配值
function kmp(s1, s2) {
var next = getNext(s2);
var j = 0;
for (var i = 0; i < s1.length;) {
for (; j < s2.length; j++) {
if (s1.charAt(i + j) != s2.charAt(j)) {
i += j > 0 ? (j - next[j - 1]) : 1;
j = next[j > 0 ? j - 1 : 0];
break;
} else if (j == s2.length - 1) {
return i;
}
}
}
return -1;
} //2.程
function kmp2(s1, s2) {
var j = 0;
var next = get_next(s2);
for (var i = 0; i < s1.length;) {
for (; j < s2.length; j++) {
if (s1.charAt(i) != s2.charAt(j)) {
j == 0 ? i++ : true;
j = next[j > 0 ? j - 1 : 0];
break;
} else if (j == s2.length - 1) {
return i - j;
}
i++;
}
}
return -1;
} //3.也正是由于i值的大小随着j值的大小进行改变,
// 使得被查找字符串仅被遍历一次即可得到解。
// 故时间复杂度为m
// 加上获得next数组的时间复杂度就是kmp算法的总时间复杂度m+n;

KMP算法的时间复杂度与next数组分析的更多相关文章

  1. KMP算法的next函数求解和分析过程

    转自 wang0606120221:http://blog.csdn.net/wang0606120221/article/details/7402688 假设KMP算法中的模式串为P,主串为S,那么 ...

  2. 关于KMP算法中,获取next数组算法的理解

    参考:KMP入门级别算法详解--终于解决了(next数组详解) https://blog.csdn.net/lee18254290736/article/details/77278769 在这里讨论的 ...

  3. hdu3336解读KMP算法的next数组

    查看原题 题意大致是:给你一个字符串算这里面全部前缀出现的次数和.比方字符串abab,a出现2次.ab出现2次,aba出现1次.abab出现1次.总计6次. 而且结果太大.要求对1007进行模运算. ...

  4. KMP算法解析(转自图灵社区)

    KMP算法是一个很精妙的字符串算法,个人认为这个算法十分符合编程美学:十分简洁,而又极难理解.笔者算法学的很烂,所以接触到这个算法的时候也是一头雾水,去网上看各种帖子,发现写着各种KMP算法详解的转载 ...

  5. 深入理解KMP算法之续篇

    前言: 纠结于KMP已经两天了,相较于本人之前博客中提到的几篇博文,本人感觉这篇文章更清楚地说明了KMP算法的来龙去脉. http://www.cnblogs.com/goagent/archive/ ...

  6. kmp算法简明教程

    在字符串s中寻找模式串p的位置,这是一个字符串匹配问题. 举例说明: i = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 s = a b a a c a b a a a b a a ...

  7. KMP算法的优化与详解

    文章开头,我首先抄录一些阮一峰先生关于KMP算法的一些讲解. 下面,我用自己的语言,试图写一篇比较好懂的 KMP 算法解释. 1. 首先,字符串"BBC ABCDAB ABCDABCDABD ...

  8. 利用KMP算法解决串的模式匹配问题(c++) -- 数据结构

    题目: 7-1 串的模式匹配 (30 分) 给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串 ...

  9. KMP算法字符串查找子串

    题目: 经典的KMP算法 分析: 和KMP算法对应的是BF算法,其中BF算法时间复杂度,最坏情况下可以达到O(n*m),而KMP算法的时间复杂度是O(n + m),所以,KMP算法效率高很多. 但是K ...

随机推荐

  1. setup_function和teardown_function

    setup_function和teardown_function 所有用例开始和所有用例结束只调用一次

  2. Windows SVN迁移到Linux 服务器

    一.备份VisualSVN项目 1. 现在要使用Linux作为svn服务器,之前是在windows Server 2008上的,用的是VisualSVN, 如下图所示. 2. 现在svn中有一个项目f ...

  3. 【SQL骚操作】SqlServer数据库表生成C# Model实体类SQL语句

    已知现有表T1 想快速获取cs类结构 /// <summary> /// T1 /// </summary> public class T1 { /// <summary ...

  4. MTCNN代码解读

    代码基于bm1682芯片 #include "mtcnn.hpp" #include "utils.hpp" using namespace std; usin ...

  5. (CSDN 迁移) JAVA循环删除List的某个元素

    若列表中只可能存在一个则可以用简单的循环删除,不多说. 若列表中可能存在多个,尤其是可能有多个连续的需要删除,用简单循环有可能发生异常. 需要使用迭代器(Iterator),两种具体实现: 逻辑上是一 ...

  6. Android组件化aar躺坑记:ButterKnife 报 元素值必须为常量表达式错误

    背景: 项目有需求,将自己写的模块作为一个module给到大项目使用,所以准备把自己的项目打包成aar包. 一.如何将独立项目打包成aar: 1.修改module下的application 为libr ...

  7. python 必选参数、默认参数、可变参数和、关键字参数

    转自:https://www.liaoxuefeng.com/wiki/897692888725344/897693568201440 可变参数 在Python函数中,还可以定义可变参数.顾名思义,可 ...

  8. 【C++】继承和组合的概念?什么时候用继承?什么时候用组合?

    继承:通过扩展已有的类来获得新功能的代码重用方法 组合:新类由现有类的对象合并而成的类的构造方式 何时用继承?何时用组合? 1.如果二者间存在一个"是"的关系,并且一个类要对另外一 ...

  9. day02——while、字符串格式化、运算符、编码初识

    day02 while--关键字(死循环) 格式:while 条件: ​ 循环体 print(1) while True: print("痒") print("鸡你太美& ...

  10. gym101480

    A. ASCII Addition 模拟 #include <iostream> #include <sstream> #include <algorithm> # ...