如需转载,请保留本文链接.
首先先将《大话数据结构》关于KMP算法的讲解部分贴上,本文不提供下载链接,也不会将电子书作为资料留百度云,需要电子书的各位,请自行寻找电子版.
关于上述的KMP算法种的next数组的推导部分,一直不是很明白,本贴是关于上述部分的学习推导记录.
以书中字符串为例:
1|2|3|4|5|6|7|8|9|
a|b|a|b|a|a|a|b|a|
0|1|1|2|3|4|2|2|3|
string T = "ababaaaba";
int i = 1;j = 0;//这里最让我费解的其实是序列号,只要明白本书中的KMP算法,序列号都是从1开始计算的,就会好理解了很多.
next[1] = 0;
while(i<T[0])//或者写成T.Length
{
if(j == 0 || T[i] == T[j])//T[i]代表后缀的第一个字符,T[j]代表前缀中的某一个字母,j记录了当前相等的字符个数
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];//所有部分匹配值均取自j的数据,且,满足if条件时,计算出的是下一个i值对应的部分匹配数据,这就意味着next[j]的值永远小于j,
//但是关于j的回溯个数,目前并没有很好的理解,初步认为只是利用next[j]值小于j值进行回溯,跟当前的前后缀相等字符数无关
}
}
以下为while循环详细分解,记录学习过程.
第一步:由于前缀与后缀均来自于子串,部分匹配表则是子串的自我匹配程度反应,那么当子串长度为1时,不存在前缀与后缀,由此可得:next[1] = 0;
第二步:i = 1;j = 0;满足if判断条件,i,j++;next[2] = 1;此时i = 2;j = 1;
第三步:i = 2;j = 1;
T[i = 2] = "b";
T[j = 1] = "a";-------------"ab"[前缀与后缀相等个数的下一字符索引值,后缀首字符]
else
{
j = next[j] = next[1] = 0;
}
j = 0;
i,j++;
next[3] = 1;//此时i = 3;j = 1;
第四步:i = 3;j = 1;
T[i = 3] = "a";
T[j =1] = "a";----------"aba"[前缀与后缀相等的个数的下一字符索引值,b,后缀首字母]
i,j++;
next[4] = 2;//此时i = 4;j = 2;
第五步:i = 4;j = 2;
T[i = 4] = "b";
T[j = 2] = "b";----------"abab"[a,前缀与后缀相等的个数的下一字符索引值,a,后缀首字母]
i,j++;
next[5] = 3;//此时i = 5;j = 3;
第六步:i = 5;j = 3;
T[i = 5] = "a";
T[j = 3] = "a";-----------"ababa"[a,b,前缀与后缀相等的个数的下一字符索引值,b,后缀首字母]
i,j++;
next[6] = 4;//此时i = 6;j = 4;
第七步:i = 6;j = 4;
T[i = 6] = "a";
T[j = 4] = "b";-------"ababaa"[a,b,a,前缀与后缀相等的个数的下一字符索引值,a,后缀首字母]
else
{
j = next[4] = 2;//j值进行回溯
}
j = 2;
T[j = 2] = "b";-------------"ababaa"[a,?,a,b,a,后缀首字母]不确定含义,暂用问号代替
elst
{
j = next[2] = 1;//j值进行回溯
}
j = 1;
T[j = 1] = "a";---------------"ababaa"[?,b,a,b,a,后缀首字母]
与T[i = 6]进行对比
i,j++;
next[7] = 2;//此时i = 7;j = 2;
第八步:i = 7;j = 2;
T[i = 7] = "a";
T[j = 2] = "b";---------"ababaaa"[a,前缀与后缀相等的个数的下一字符索引值,a,b,a,a,后缀首字母]
else
{
j = next[j] = next[2] = 1;
}
j = 1;
T[j = 1] = "a";-----------------"ababaaa"[前缀与后缀相等的个数的下一字符索引值,b,a,b,a,a,后缀首字母]
i,j++;
next[8] = 2;//此时i= 8;j = 2;
第九步:i = 8;j = 2;
T[i = 8] = "b";
T[j = 2] = "b";---------------"ababaaab"[a,前缀与后缀相等的个数的下一字符索引值,a,b,a,a,a,后缀首字母]
i,j++;
next[9] = 3;//此时i = 9;j = 3;
此时关于字符串"ababaaaba"的部分匹配表完全推导完毕,答案与书上结果一直,但是关于i = 6时,j回溯如何做解释,还需要再看,我在另外的字符串"aaaaabbbc"中,j的回溯每次回溯一位,得到的部分匹配表为:012345511,欢迎留言指正,结束.