KMP算法以及next函数值、nextval函数值的计算方法
数据结构中串涉及的内容即串的模式匹配,比较难理解的KMP算法,难在next函数值和nextval函数值的求解
一、问题描述
给定一个主串S及一个模式串P,判断模式串是否为主串的子串;若是,返回匹配的第一个元素的位置(序号从1开始),否则返回0;
先了解一下最简单直观的模式匹配算法BF(Brute-Force)算法,对理解KMP算法做个铺垫!
1、BF算法
假设S=“BBC ABCDAB ABCDABCDBADE”,P=“ABCDABD”。
- 分别利用计数指针i和j指示主串S和模式串P中当前正在比较的字符位置,i的值可以指定,j初值为1;
- S.ch[i]和P.ch[j]比较,若相等,则i和j分别指示串的下个位置,继续比较后续字符;
- 若不相等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再新和模式串的第一个字符(j=1)比较。
1、当S=“BBC ABCDAB ABCDABCDBADE”
与P="ABCDABD"进行匹配时:
串S BBC ABCDAB ABCDABCDBADE
串P ABCDABD
因为B与A不匹配,模式串后移一位。
-
直到文本串有一个字符与模式串中的第一个字符相同为止,然后逐一比较下一个字符,发现“空格”与“D”不匹配。
BBC ABCDAB ABCDABCDBADE ABCDABD
3.重复第1第2步,能找到文本串中有“ABCDABD”与模式串相匹配,但效率很慢。
下面我们来了解另一种改进的模式匹配算法。
2、KMP算法
KMP算法,其改进在于,每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
KMP算法是在已知模式串的next函数值的基础上执行的,那么,如何求得模式串的next函数值呢?(模式串根据next函数值向右“滑动”距离此函数值仅取决于模式串本身)
3、计算next函数值
【举例】
串“ababaaababaa”的next数组为
- next[1]=0
- next[2]=1
(这两个值是约定的)
- next[3]:"ab"没有相同的前缀或后缀,所以模式串又得从头开始匹配,因此next[3]=1;
- next[4]:“aba"的最长公共串是"a”,前三位匹配上了,并且第一位和第三位相同,因此可以将模式串整体向右移动,直到将原来的第一位移到原来的第三位上,继续进行匹配,而原来模式串指针指着的第四位现在指向第二位了,因此next[4]=2;
- next[5]:“abab"的最长公共串是"ab”,用同样的方法得出next[5]=2;
以此类推······
- next数组为:
0 1 1 2 3 4 2 2 3 4 5 6
4、计算nextval函数值
【举例】
串“ababaabab”的nextval为
总结如下:
1、nextval[1]和next[1]的值一样,为0;
2、如果s[i]==s[j],则nextval[i]=nextval[j];反之,nextva