KMP算法实现字符串的模式匹配的时间复杂度比朴素的模式匹配好很多,但是它时间效率的提高是有前提的,那就是:模式串的重复率很高,不然它的效率也不会凸显出来。在实际的应用中,KMP算法不算是使用率很高的一个算法,但是它的核心的那点东西却是使用率很高的,那就是next前缀数组的求解思路。在这次笔记中就单独摘出来,说一下前缀数组的求解。


1. next前缀数组的定义

不管做题还是推到算法,永远记住定义,这时最重要的东西。


2. next数组的暴力求解

这种方法的主要思路是:

为了求解nj的值,把的所有的前缀和后缀都找出来,然后从最大的开始匹配,直到找到合适的最长公共前缀后缀。如果没有,那么nj的值就是0。

前后缀的选取方式:

暴力算法就是在这里面不断的从最大的那个前缀和后缀逐一的匹配。

算法描述:

(1) 根据定义,初始化n[0] = –1。

(2) 从模式串的下标为1的位置,依次遍历整个模式串。对于每一个字符,当到达其下标j时,令k=j-1。

(3) 寻找它前面的字符串的最大公共前缀后缀,也就是判断的真假?

(4) 如果满足条件,令next[j]=k;如果不满足条件k--,继续执行(3)的步骤,直到k==0,然后令next[j]= 0。

代码实现:

#include <iostream>
#include <stdlib.h>
bool IsPatternMatch(char *p, int compareNum, int totalNum);
void ViolentGetNext(char *p, int *next); void main()
{
int next[];
char *str = "agctagcagctagctg";
ViolentGetNext(str, next); system("pause");
} void ViolentGetNext(char *p, int *next)
{
int pLen = strlen(p);
int k = ;
next[] = -; for(int j = ; j < pLen; j++)
{
k = j - ;
while(k > )
{
if(IsPatternMatch(p, k , j))
break;
else
k--;
}// while next[j] = k;
}// for
}
//param:copareNum代表了要比较的字节数
//param:totalNum代表了要比较的字节数
//上面的两个参数的作用就是定界前缀和后缀可能的范围
bool IsPatternMatch(char *p, int compareNum, int totalNum)
{
int i = ;
int j = totalNum - compareNum; for(; i < compareNum; i++, j++)
{
if(p[i] != p[j])
{
return false;
}
} return true;
}
具体的例子,假设字符串为ABCDABD
n[]的求解过程如下:
k=
ABCD≠BCDA,k=
ABC≠CDA,k=
AB≠DA,k=
A==A,n[]=k

3. next数组的递归求解

暴力求解每次在计算next[j]的时候都是独立的,而实际上求解next[j+1]是可以利用到next[0…j]的,这里的递归算法就是这样实现的。

设模式串为,现在已经计算出了next[0…j],如何计算next[j+1]?

利用前面求解的数值(这也是算法改进的地方,不让每个next元素都独立的计算),若已知next[j]=k,则对于模式串,肯定有这样的关系:

所以算法的描述可以是这样的:

(1) 如果k==-1(只有第一个字符的next值是-1),说明现在的位置是第二个位置,还不能算第二个它本身,所以next[j+1]=0,算法结束。

(2) 如果,理解这里的k是怎么从next[j]的值转换到了字符的下标值。则next[j+1]=k+1,算法结束。

提示:前面有分析过,求解next数组的过程的快捷方法就是不让他们独立的计算,还是继承前面计算好了的对称性。知道了next[j]的对称性,只需要在考察一下前缀和后缀的下一个字符是否相等就可以了。pk和pj就是之前最长前缀和后缀的下一个字符。

(3) 那么这个k’从哪里来的呢?看这个式子的两端就知道k’=next[k]。理解好上面的这个式子,就知道k‘是怎么来的了。

(4) 将k’赋值给k,转到步骤(1)。

代码实现:

//the recursion method to abtain the next array
//pLen is the length of the string
void RecursionGetNext(char *p, int pLen, int *next)
{ if(pLen == )
{
next[pLen - ] = -;
return;
} RecursionGetNext(p, pLen - , next); //pLen represents the number of the string
//pLen - 1 represents the index of the last character,that is the character that will be calculated in the next array.
//pLen - 1 - 1 represents the index of the sub-last character that has been calculated in the next array.
int k = next[pLen - ]; //k==-1 is a label showing that there is no prefix matching with postfix and the currently added character can not match neither.
//k==0 can only show that there is no prefix mathching with postfix,but pk may be match with pj
while(k >= )
{
if(p[pLen-] == p[k])
{
break;
}
else
{
k = next[k];
}
}//while next[pLen -] = k + ; }//RecursionGetNext()

4. next数组的递归展开求解

void GetNext(char *p, int *next)
{
int pLen = strlen(p);
int j = ;
int k = -;
next[] = -; while(j < pLen - )
{
//accroding to the depiction of the algorithm,the procedure can be programmed below:
//if(k == -1)
//{
// ++j;
// ++k;
// next[j] = k;
//}
//else if(p[j] == p[k])
//{
// ++j;
// ++k;
// next[j] = k;
//}
//but the fist two procedure can be reduced to one case: //p[j] == p[k] shows that we can inherite the feature of the string that matched alreay
//k==-1 shows two circumstance: 1.the beginning of the algorithm 2.there is no matched prefix and postfix and the last character is also defferent with the first one
if(k == - || p[j] == p[k])
{
++j;
++k;
next[j] = k;
}
else
{
k = next[k];
}
}//while
}

5. Reference Link

@wzhang1117的博客:https://www.zybuluo.com/wzhang1117/note/27431

KMP算法番外篇--求解next数组的更多相关文章

  1. 数据结构和算法 – 番外篇.时间测试类Timing

    public class Timing { //startingTime--用来存储正在测试的代码的开始时间. TimeSpan startingTime; //duration--用来存储正在测试的 ...

  2. 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV

    这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...

  3. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  4. 可视化(番外篇)——SWT总结

    本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...

  5. python自动化测试应用-番外篇--接口测试1

    篇1                 book-python-auto-test-番外篇--接口测试1 --lamecho辣么丑 1.1概要 大家好! 我是lamecho(辣么丑),至今<安卓a ...

  6. [uboot] (番外篇)uboot之fdt介绍

    http://blog.csdn.net/ooonebook/article/details/53206623 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

  7. C++雾中风景番外篇:理解C++的复杂声明与声明解析

    在学习C系列语言的过程之中,理解C/C++的复杂声明一直是初学者很困扰的问题.笔者初学之时也深受困扰,对很多规则死记硬背.后续在阅读<C专家编程>之后,尝试在编译器的角度来理解C/C++的 ...

  8. [uboot] (番外篇)uboot之fdt介绍 (转)

    以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例 [uboot] uboot流程系列:[project X] tiny210(s5pv210)上电启动流程(B ...

  9. (八)羽夏看C语言——C番外篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

随机推荐

  1. oracle job 定时执行 存储过程

    oracle job 定时执行 存储过程   一:简单测试job的创建过程案例: 1,先创建一张JOB_TEST表,字段为a 日期格式 SQL> create table JOB_TEST(a ...

  2. canvas学习笔记(一)-认识canvas

    canvas是html5新增的一个标签,主要用于图形的绘制.我们可以把它理解为是浏览器给我们提供了一个画板,至于要绘制怎样的画卷,就看神笔马良你的主意了.而在canvas上绘制图形使用的笔,就是js了 ...

  3. Python 学习之中的一个:在Mac OS X下基于Sublime Text搭建开发平台包括numpy,scipy

    1 前言 Python有许多IDE能够用,官方自己也带了一个,Eclipse也能够. 但我在使用各种IDE之后,发现用Sublime Text是最好用的一个.因此.我都是用Sublime Text来编 ...

  4. ExtJs中的Grid具体操作(笔记及心得)

    一.基本操作步骤 var cm=new Ext.grid.ColumnModel([ //对列的定义,cm是它的简写,作为真个表格的列模式,需要首先创建的{header:'编号',dataIndex: ...

  5. iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见

    iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见 (2015-12-05 12:48:20)[编辑][删除] 转载▼     首先我们先明确一下问题: 1.因为UI是在主线 ...

  6. Java动态代理机制——Cglib

    上一篇说过JDK动态代理机制,只能代理实现了接口的类,这就造成了限制.对于没有实现接口的类,我们可以用Cglib动态代理机制来实现. Cglib是针对类生成代理,主要是对用户类生成一个子类.因为有继承 ...

  7. 关于eclipse(64位)下aptana插件安装报错问题解决

    最近一直没有写过js,换了新电脑以后,eclipse下的aptana插件也没有装过,这几天要写js想重新把aptana装上,但是不知怎的,link方式.在线安装方式还有离线包下载下来利用eclipse ...

  8. easyui给select控件绑定change事件

    一般的做法是使用jQuery来绑定,例如: $("#id").change(function(){ alert("change事件绑定"); }); 当给sel ...

  9. JS笔记 入门第四

    小测试: 注意:取消所有的设定可以直接使用 document.getElementById("txt").removeAttribute("style"); 这 ...

  10. android小知识之EditText输入框之值监控以及类型限制(数字,英语字母,下划线,是否为星号密码)

    1.设置EditText的值监听事件 . <span style="font-size:14px;color:#990000;"> EditText ed=new Ed ...