KMP算法学习记录----《大话数据结构》部分匹配表学习部分

时间:2022-02-11 00:09:19

如需转载,请保留本文链接.

首先先将《大话数据结构》关于KMP算法的讲解部分贴上,本文不提供下载链接,也不会将电子书作为资料留百度云,需要电子书的各位,请自行寻找电子版.

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

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,欢迎留言指正,结束.