KMP算法next & nextval探讨
来源:互联网 发布:rar压缩软件mac版 编辑:程序博客网 时间:2024/06/06 19:48
摘要:本文在阅读清华大学教授严蔚敏《数据结构》一书的基础上,同时参照互联网上已有KMP相关文章的前提下,对KMP匹配过程中next与nextval数组的计算,做了图形化探讨。并一句话概括计算原则——计算next[j]函数值,必从j-1位置开始(不是j),以j-1为节点号,next[j-1]为链表尾指针,一直往前查找,直到找到与arr[j-1]值相同的位置时(k)停止,则此时next[j]=next[k]+1。(注:将上述表格抽象为链表,从后往前的链表)。
目录:
- 何为KMP算法模式匹配的一种改进算法
- next函数值计算
- 示例next5求法
- 示例next3求法
- nextval函数值计算
- 附nextnextval测试
何为KMP算法——模式匹配的一种改进算法
这种算法是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的,因此人们称它为克努特—莫里斯—普拉特算法(简称为KMP算法)。此算法可以在O(m+n)
的时间数量级上完成串的模式匹配操作。
其改进在于:每当一趟匹配过程中出现字符比较不等时,不需要回溯 i 指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续进行比较。
next函数值计算
模式串的next函数定义:
由此定义可推出下列模式串的next函数值:
计算next总原则(非常重要):
计算next[j]函数值,必从j-1位置开始(不是j),以j-1为节点号,next[j-1]为链表尾指针,一直往前查找,直到找到与arr[j-1]值相同的位置时(k)停止,则此时next[j]=next[k]+1。(注:将上述表格抽象为链表,从后往前的链表)
- 务必准确把握——j、模式串、next[j]的不同含义,不要搞混了。
几大注意事项:
next[0]一般不使用,直接将next[1]=0,next[2]=1,j从1开始,j和next[j]有一一对应关系;(注:如果非要使用next[0]的话,则置next[1]=-1,next[2]=0)
一个特殊状态,如果按照上述总原则,无法找到与arr[j-1]值相同的位置。则一律置next[j]=1。
为了形式化,首先,将上述表格转化为双亲表示法树状结构如下:
示例next[5],求法;
1.表格求解法如下:
2.双亲节点表示法,求解过程如下:
示例next[3],求法;
以下留下几个表格,供手动模拟练习一下计算过程:
nextval函数值计算
前面定义的next函数在某些情况下尚有缺陷(进行了某些不必要的匹配,如下图)。为了解决该问题引入了nextval对next进行修正。
接下来继续使用上述,问题为材料对next进行修正:
在计算出next之后,得出nextval十分之简单,用以下代码表示更直接:
if (arr[j]==arr[next[j]]){ next[j] = next[next[j]];}
就是判断arr[j]与其next[j]所对应的arr[next[j]]是否相同,相同则修正,否则不需要修正。
附next/nextval测试:
#include <stdio.h> int next[9]; //不修正 int getNextj(char arr[], int j){ int k = j-1; while (k > 0){ //③比较arr[j-1]是否等于arr[next[j-1]] if (arr[j-1]==arr[next[k]]){ return next[k]+1; } //④不等于,继续找下去 k = next[k]; } //⑤未找到,恒置1 return 1; } //修正 void getNextVal(char arr[]){ int j; for (j = 1; j < 9; ++j){ //⑥修正,如果arr[j]==arr[next[j]]则修正 if (arr[j]==arr[next[j]]){ next[j] = next[next[j]]; } } } int main(void){ char arr[] = " abaabcac";//前面有一空格,T[]从1开始 int j; //①初始化 next[1] = 0; next[2] = 1; //②逐个求next for ( j = 3; j <= 8; ++j ){ next[j] = getNextj(arr,j); } //打印 printf("----next---\n"); for ( j = 1; j <= 8 ;++j){ printf("%d ",next[j]); } //修正 getNextVal(arr); printf("\n----nextval---\n"); for ( j = 1; j <= 8 ;++j){ printf("%d ",next[j]); } printf("\n"); return 0; }
—-next—
0 1 1 2 2 3 1 2
—-nextval—
0 1 0 2 1 3 0 2
Press any key to continue
- KMP算法next & nextval探讨
- KMP算法 next nextval求值
- KMP算法之Next和Nextval详解
- 初探KMP算法之next/nextval
- KMP中的next和nextval的算法
- KMP算法 next与nextval的求解
- KMP next nextval
- KMP next nextval
- KMP算法中next和nextval数组的计算方法
- KMP算法(求模式串的next及nextval值)
- KMP算法中next和nextval数组的求解
- 手动计算KMP算法的Next数组与NextVal数组
- 详解又详解KMP中的next和nextval的算法
- KMP算法求next数组和nextval…
- KMP模式匹配算法中next和nextval的求解
- KMP模式匹配算法中next和nextval的求解
- KMP算法求next数组和nextval数组
- KMP中next和nextval算法简析
- 线性表
- 不用加减乘除做加法。。。二进制运算
- 文章标题
- 4-3 求链式表的表长 (10分) PTA
- UVA 10498 食物分配 单纯形算法
- KMP算法next & nextval探讨
- 无向图的割与桥
- SQL SERVER数据库定义和建立
- CentOS防火墙打开和关闭端口
- js的True、False判断
- centos7 安装virtualbox虚拟机
- Lintcode35 Reverse Linked List solution 题解
- Git提交项目.gitignore的过滤规则
- Educational Codeforces Round 20 A