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. poj1657---chessboard

    对棋盘横纵坐标的解读 str1="f3" str2="e9" x=abs(str1[0]-str2[0]) y=abs(str1[1]-str1[1]) 如果x ...

  2. Lua学习2 Lua小框架的搭建

    看了上一篇Lua环境搭建具体http://blog.csdn.net/liuwumiyuhuiping/article/details/9196435 为了方便学习. 具体新开始搭建一下学习的小框架. ...

  3. 2014年辛星解读Javascript之DOM之冒泡和捕获

    上篇博客提到了Javascript事件绑定函数的三个參数.第一个是一个event.第二个是一个function.第三个是一个布尔变量.它用于指定事件传递的顺序,分为冒泡和捕获两种方式,接下来我们将揭开 ...

  4. Android流式布局实现

    查看我的所有开源项目[开源实验室] 欢迎增加我的QQ群:[201055521],本博客client下载[请点击] 摘要 新项目用到了一种全新布局----Android标签流式布局的功能,正好一直说给大 ...

  5. jQuery中$.each的用法

    jQuery中$.each的用法   本文导读:jQuery中each()函数是基本上所有的框架都提供了的一个工具类函数,通过它,你可以遍历对象.数组的属性值并进行处理.jQuery提供的each方法 ...

  6. Linux 文件内容转码

    文件内容的转换: iconv -f GB2312 -t UTF-8 gb1.txt >gb2.txt-f, –from-code=名称 原始文本编码-t, –to-code=名称 输出编码-o, ...

  7. iOS隐藏tabBar的方法

    两种方法用来隐藏tabBar 1.在本页面隐藏 #pragma mark - 隐藏tabBar - (void)viewWillAppear:(BOOL)animated{ self.tabBarCo ...

  8. JS脚本验证大全

    /** * 2009-10-01 * 贺  臣 * 情  缘 * js各种表单数据验证 *//***************************************************** ...

  9. html object元素

    知道object是播放音频,但是想了解具体点,百度一下,感觉模模糊糊的,感觉看不大明白,最后找到一个解释比较详细,先从应用,到解释具体属性, 具体网址是: http://www.w3school.co ...

  10. 解决Thinkpad E450 外接显示器后没有声音的问题

    昨天把公司配的ThinkPad E450 带回来了,今天用的时候一切正常没什么问题. 因为要看边看视频边做点别的,我就外接一台显示器,说出来我的这台显示器,你们绝对想不到是什么 显示器.我的这台显示器 ...