next数组的历史

  有关字符串的模式匹配算法中,比较容易写出的是朴素的匹配算法也就是一种暴力求解方式,但是由于其时间复杂度为子串长度和主串长度的乘积,例如strlen(subStr) = n,strlen(mainStr) = m,则其时间复杂度为O(mn)。

  为了能够得到更有效的匹配算法,D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特--莫里斯--普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。这也即是KMP算法的设计思想。

next数组的求解思路

  求next数组,next[j]表示,当模式串j位置与主串i位置处发生不匹配时,i指针不回溯,j指针回溯到next[j]的位置。

  对于求next[j]有三种情况:

1、j = 0时,next[j] = -1;//即模式串的第一个字符与主串i位置发生不匹配,应将i跳过当前位置,从下一个位置和模式串的第一个字符继续比较。

2、假设已知next[j] = k,即subStr[0,...,k-1] = subStr[j-k,j-1]。当subStr[k] = subStr[j]时,也就是说模式串满足subStr[0,...,k] = subStr[j-k,j],可以得知next[j+1] = k + 1 = next[j] + 1;

3、当subStr[k] != subStr[j]时,就需要从k位置之前去查找与subStr[j]匹配的位置,假设为j'。这样问题又可以转化为第二种情况,即next[j+1] = next[j'] + 1 = k' + 1。

三种求解next数组的算法

  但是如何去求解next数组呢?有关这个问题,我思考了很长时间,下面给出几种算法:

  算法一,严格根据next数组的定义:

 1 void getNext(char subStr[],int next[])
 2 {
 3     int i = 1, j = i - 1,k = -1;
 4     next[0] = -1;
 5     while (i < strlen(subStr))
 6     {
 7         //k = -1时表示j指针回溯到第一个字符的位置
 8         //subStr[k] == subStr[i-1]表示第k个字符和i - 1个字符相等,属于情况二
 9         if (k == -1 || subStr[k] == subStr[i-1])
10         {
11             next[i] = k + 1;
12             k = next[i];
13             i++;
14         }
15         //情况三,不相等的话,要回溯j指针,subStr[j'] = subStr[i-1]的位置j'
16         else
17         {
18             int t = i - 2;
19             while (t>=0)
20             {
21                 if (subStr[t] == subStr[i - 1])
22                 {
23                     j = t;
24                     break;
25                 }
26                 t--;
27             }
28             if (t < 0)
29                 j = 0;
30             k = next[j];
31         }
32
33     }
34 }

  算法二,算法的设计思想和算法一大致相同

void getNext(const char P[], int next[])
{int q, k;int m = strlen(P);next[0] = -1;//模版字符串的第一个字符的最大前后缀长度为0for (q = 1; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
    {k = next[q - 1];while (k > 0 && P[q - 1] != P[k])//迭代地求出P[0]···P[q]的最大的相同的前后缀长度k
        {k--;}if (P[q-1] == P[k])//如果相等,那么最大相同前后缀长度加1
        {k++;}if (k == -1)k = 0;next[q] = k;}
}

  算法三,更加优化的求解next数组的算法

void getNext(const char subStr[], int next[])
{int i = 1, j = -1;next[0] = -1;while (i < strlen(subStr)){//i从0开始的,属于情况二//j是前后缀长度if (j == -1 || subStr[i] == subStr[j]){i++;j++;next[i] = j;}//情况三,不同则j指针回溯elsej = next[j];}
}

  现在来进行总结一下,对于算法一和算法二来说,它们的时间复杂度是一样的,但是相对于算法三来说,虽然不如算法三高效,但是比较容易理解!

PS:如果有误的地方,请指出,共同进步!

那些有关求解next数组的算法相关推荐

  1. .net 遍历数组找重复值写入一个新数组_面试 | 数组类算法精析

    点击上方蓝字设为星标 每周一.三.五上午 8:30 准时推送 下面开始今天的学习- 面试中的算法问题,有很多并不需要复杂的数据结构支撑.就是用数组,就能考察出很多东西了.其实,经典的排序问题,二分搜索 ...

  2. 两种方法求解 正数数组中 两个数相减 的最大值

    一,问题描述 给定一个正数数组arr(即数组元素全是正数),找出该数组中,两个元素相减的最大值,其中被减数的下标不小于减数的下标. 即求出: maxValue = max{arr[j]-arr[i] ...

  3. July文章《从头到尾彻底理解KMP(2014年8月22日版)》中,关于求解next数组,进一步理解如何递归前缀索引 k=next[k]

    写在最前面,本文是对July文章中求解next数组时,递归前缀索引 k=next[k],这个小部分的解释,详细的KMP算法原理,看看July的文章就好了. 看了July的文章<<从头到尾彻 ...

  4. js实现多维数组组合算法

    前言 最近在搞一个航线管理系统,如图,需要根据起始点,中转点和终点绘制航线图.这就涉及到点与点之间的组合算法.用专业点的说法,就是多维数组之间的元素组合.就拿上面的航线图来说,我们可以抽象为下面的数组 ...

  5. UA SIE545 优化理论基础4 对偶理论简介6 求解对偶问题的梯度算法

    UA SIE545 优化理论基础4 对偶理论简介6 求解对偶问题的梯度算法 这一讲我们介绍求解对偶问题的另一个算法--梯度算法(gradient method). 假设原问题为 min⁡x∈Xf(x) ...

  6. UA SIE545 优化理论基础4 对偶理论简介4 求解对偶问题的割平面算法

    UA SIE545 优化理论基础4 对偶理论简介4 求解对偶问题的割平面算法 这一讲我们介绍一个求解对偶问题的算法--割平面算法(cutting plane algorithm). 假设原问题为 mi ...

  7. 如何求解问题--数据结构与算法入门

    如何求解问题–数据结构与算法入门 在学习数据结构与算法前,我们大多有这样的困惑,难道学习了数据结构与算法就能帮助我们解决学习Java.Python时的大作业吗?数据结构与算法是什么? 回答这个问题之前 ...

  8. Algorithm:C+语言实现之数组相关算法(和为定值的两个数、和为定值的m个数、荷兰国旗、长度为2n的洗牌算法、任意长度数组的洗牌算法)

    Algorithm:C+语言实现之数组相关算法(和为定值的两个数.和为定值的m个数.荷兰国旗.长度为2n的洗牌算法.任意长度数组的洗牌算法) 目录 数组 1.寻找和为定值的两个数 2.和为定值的m个数 ...

  9. JavaScript数组去重算法实例

    本文主要介绍了JavaScript数组去重算法,结合实例形式总结分析了JavaScript数组去重相关的读写.遍历.比较.排序等操作及算法改进相关实现技巧,需要的朋友可以参考下 测试用例: arr = ...

最新文章

  1. 那位五十多岁的创业者给我的启示!
  2. 数据分析 | 带你零基础入门数据挖掘(附代码)
  3. Qt Creator导出QML
  4. 拋棄虛擬機,微軟實驗讓我們在線做(一)
  5. 查看自己设置的jvm参数
  6. HTML基础(part4)--常用标签之图片标签
  7. 那些查了无数遍的问题
  8. 第一个shell脚本——修改配置文件
  9. java计算机毕业设计实验室耗材管理系统源码+系统+数据库+lw文档+mybatis+运行部署
  10. 自定义更改虚拟机中Ubuntu的ip地址
  11. 怎样把多个excel文件合并成一个
  12. Mac 技巧|忘记了开机密码的解决办法
  13. 生活随记-很有意思的评论
  14. 【清晖诗社】“立秋” 诗意浓,佳作有奖征集ing!
  15. Jetson Tegra X系列刷机教程
  16. a=a*10+b型题目
  17. 从1.0到4.0,酒类新零售还能跑出几个1919和酒仙网?
  18. 双向可控硅的触发电路设计
  19. 2018网易校招移动安全工程师笔试题
  20. ARMv8-a架构简介

热门文章

  1. JAVA bridge设计模式,java设计模式之Bridge
  2. ssm 新建拦截器_拦截器在springboot项目和ssm架构项目的应用
  3. idea 填充变量类型_填充IntelliJ IDEA项目
  4. python 装饰器装饰类
  5. MongoDB Element Query Operators(元素判断操作符)
  6. Centos 网络配置
  7. gfdmp和mysql,《高性能MySQL》读书笔记--锁、事务、隔离级别
  8. python特征数据类型及常用操作对比_更高效的利用Jupyter+pandas进行数据分析,6种常用数据格式效率对比!...
  9. golang | 变量-字符串练习
  10. android截取网页图片,安卓版谷歌浏览器很快将获得滚动截图功能 可以用来截取整个网页...