KMP模式匹配算法中next和nextval数组的快速求解
来源:互联网 发布:office for ubuntu 编辑:程序博客网 时间:2024/05/13 08:20
在这里,不再对大名鼎鼎的KMP算法做过多赘述,如想了解可参考http://blog.csdn.net/v_JULY_v/article/details/6111565,写的很好!
首先,阐明一下这篇文章的目的:快速求解模式串的next以及nextval数组。当然这里面的模式串都比较短,在笔试或者面试的时候很有可能遇到,因此,如何快速求得是至关重要的!
废话不多说,我们直接切入主题,即关于next数组是如何求解的。而nextval数组是对next数组的改进,有这么个循序渐进的过程,所以先从next数组说起。我们都知道:next数组是表征模式串p自身的匹配程度的,所以我们先从一个串的前缀和后缀表达式说起。
串
前缀
后缀
最大长度
a
无
无
0
aa
a
a
1
ab
a
b
0
aba
a,ab
a,ba
1
abab
a,ab,aba
b,ab,bab
2
ababa
a,ab,aba,abab
a,ba,aba,baba
3
ababab
a,ab,aba,abab,ababa
b,ab,bab,abab,babab
4
abababa
a,ab,aba,abab,ababa,ababab
a,ba,aba,baba,ababa,bababa
5
aaaaaab
a,aa,aaa,aaaa,aaaaa,aaaaaa
b,ab,aab,aaab,aaaab,aaaaab
0
以上表中串ababa为例:其前缀式有a,ab,aba,abab,而后缀式有a,ba,aba,baba,前缀与后缀匹配的串为:a,aba,因此串ababa的前缀与后缀的最大匹配长度为3。
好了,到这里可以直接来求next数组了!
这里,以模式串p="ababab"为例吧!
1. next[0]=-1,这个应该没有疑问的,取-1是因为字符串都是从下标0开始索引的(当然,也可以取为0,这时字符串的下标就要从1开始了);
2. next[1]=?我们知道p[1]=b,p[1]之前的子串只有"a",而字符串"a"的前缀与后缀最大匹配长度为0(上表第二行所示),因此,有next[1]=0;
3. next[2]=?从上一步的求解中可发现:欲求next[i],先找子串p[0~i-1]的前缀与后缀最大匹配长度,这也是与next数组的定义相吻合的next[k]=max{k|p[0~k-1]=p[i-k~i-1]},当然如果没有这样的k的话,就取next[k]=0,例如p[0~i-1]="ab"时;因此,next[2]=0;
知道了如何求解next数组的方法,做起来就很容易了!
a b a b a b
-1 0 0 1 2 3
a a a a a a b
-1 0 1 2 3 4 5
a b a b b a b a c b a a b
-1 0 0 1 2 0 1 2 3 0 0 1 1
好了,到这里相信你已经可以独立的算出模式串的next数组了,下面,我们由next数组来推导nextval数组!
首先,对next数组做一个延伸,即多求一位next[i+1]:
a b a b a b
-1 0 0 1 2 3 4
a a a a a a b
-1 0 1 2 3 4 5 0
a b a b b a b a c b a a b
-1 0 0 1 2 0 1 2 3 0 0 1 1 2
注意上文中的红色数字,它们是由整个模式串的前缀后缀的最大匹配长度得来的。
a b a b a b
-1 0 0 1 2 3 4
-1 0 -1 0 -1 0
a a a a a a b
-1 0 1 2 3 4 5 0
-1 -1 -1 -1 -1 -1 5
a b a b b a b a c b a a b
-1 0 0 1 2 0 1 2 3 0 0 1 1 2
-1 0 -1 0 2 -1 0 -1 3 0 -1 1 0
蓝色字体的就是nextval数组,不知道大家有没有看出一些规律来?
首先,还是从nextval对next的改进之处说起吧!
void getnext(char p[]){next[0]=-1;int lenp=strlen(p);int i=0,j=-1;while(i!=lenp-1){if(j==-1||p[i]==p[j]){++i;++j;next[i]=j;}elsej=next[j];}}
void getnextval(char p[]){nextval[0]=-1;int i=0,j=-1,lenp=strlen(p);while(i!=lenp-1){if(j==-1||p[i]==p[j]){++i;++j;if(p[i]!=p[j])nextval[i]=j;elsenextval[i]=nextval[j];}elsej=nextval[j];}}
从上面两段代码,可发现nextval对next的改进之处在于当p[i]==p[j]时,nextval[i]=nextval[j],而不再是nextval[i]=j。
注意到这一点之后,我们首先给出一个结论:当p[i]==p[j]时,必然有next[i+1]=next[i]+1(注意这里是next数组而不是nextval数组)。
来分析一下:
假定next[i]=k,则必有
k>=1:p[0~k-1]=p[i-k~i-1],j=k;若p[i]==p[j],—>p[0~k]=p[i-k~i] —>next[i+1]=k+1=next[i]+1;
k==0:p[0]!=p[i-1],j=0;若p[i]==p[j],—>p[0]=p[i] —>next[i+1]=1=next[i]+1;
好的,下面我们来见证一下如何从next数组来得到nextval数组:
若next[i+1]=next[i]+1,则nextval[i]=nextval[next[i]],0<=i<=strlen(p)-1;
对的,就是这么简单!
索引
0
1
2
3
4
5
6
7
8
9
10
11
12
13
模式串
a
b
a
b
b
a
b
a
c
b
a
a
b
next[]
-1
0
0
1
2
0
1
2
3
0
0
1
1
2
nextval[]
-1
0
-1
0
2
-1
0
-1
3
0
-1
1
0
上表中彩色部分一目了然!
至此,相信你已经可以快速完成next、nextval数组的求解了!
- KMP模式匹配算法中next和nextval数组的快速求解
- KMP模式匹配算法中next和nextval的求解
- KMP模式匹配算法中next和nextval的求解
- KMP算法中next和nextval数组的求解
- KMP模式匹配算法中next和nextval的求解(转)
- KMP模式匹配算法中next,nextval的分别实现
- 计算KMP模式匹配算法中next数组的代码分析及改进型KMP算法中nextval数组代码分析
- KMP算法中next和nextval数组的计算方法
- KMP算法 next与nextval的求解
- 数据结构之模式匹配KMP算法的next数组求解
- KMP算法中next数组、nextval数组的手工计算
- KMP算法中next数组和nextval数组值的推导
- KMP中的next和nextval的算法
- kmp中next和nextval的区别
- kmp中next和nextval的区别 .
- kmp中next和nextval的区别
- 计算精确串匹配算法KMP中的next和nextVal数组值
- 模式匹配 KMP算法中Next值求解
- processing的入门函数
- 成立运营商数据银行部的构想
- IOS使用正则表达式去掉html中的标签元素,获得纯文本
- 设计模式之创建者模式
- neon汇编优化实例讲解
- KMP模式匹配算法中next和nextval数组的快速求解
- max sub array and label
- CATransition type类型
- 2014-04-17-IIS asp.net配置默认文档错误
- ASP.NET创建快捷方式
- 中文FLEX例子
- Hibernate中get和load方法的区别
- 解释器模式
- Cracking The Coding Interview 4.7_暂存