KMP部分匹配表代码讲解

                                                                                            -------咬定青山不放松,立根原在破岩中

         

        大家好,周末在家学习KMP算法,却卡在了生成部分匹配表这块,不知道大家对这个算法理解的怎么样,反正我是看了半天没看明白ψ(*`ー´)ψ✄╰ひ╯,但是!!!,经过我不懈的努力与持之以恒的奋斗以及上天的眷顾。。。。还是没看出来(_(:3」∠❀)_菊花碎了一地),可就在我躺在床上一筹莫展时,灵光突然一现,所以我抓紧写篇文章记录一下先。

好的,废话不多说,代码如下:

public static int[] getPartTable(String str) {
    //部分匹配表数组
    int[] table = new int[str.length()];
    //第一个设置为 0
    table[0] = 0;
    // i用来指向部分匹配字符串末尾的字符;
    // j用来指向开始的字符;
    for (int i = 1, j = 0; i < str.length(); i++) {
        // 当j>0且前缀后缀不匹配时,使用部分匹配表中前一个表项的值
        while (j > 0 && str.charAt(j) != str.charAt(i)) {
            j = table[j - 1];
        }

        //如果前缀后缀匹配,j向后移,继续比较
        if (str.charAt(j) == str.charAt(i)) {
            j++;
        }
        table[i] = j;
    }
    return table;
}

个人认为,这段代码最难理解的是下边这一句:

// 取前一个表项的匹配值
j = sectionTable[j - 1]; 

 下面我会带大家针对模式串进行手动推演,估计大家看到最后,也就理解的差不多了。

随便举一个例子:str = "ABABAAABA";  字符串长度为9,所以要定义一个长度为9的数组用来保存部分匹配表为T;前后缀最大公共长度推导过程如下:

示例1
indexTstr
00A
10AB
21ABA
32ABAB
43ABABA
51ABABAA
61ABABAAA
72ABABAAAB
83ABABAAABA

①部分串"A"就一个字符,所以前后缀最大公共长度为0;所以T[0] = 0;

②部分串 "AB" 在①的基础上加了一个字符"B", 此时 i = 1, j = 0; 判断出str.charAt(j) != str.charAt(i),所以j = T[i] = j = 0;

③部分串 "ABA" 在②的基础上加了一个字符"A", 此时i = 2, j = 0; 判断出str.charAt(j) == str.charAt(i),所以j++,T[i] = j = 1;

④部分串 "ABAB" 在③的基础上加了一个字符"B", 此时i = 3, j = 1; 判断出str.charAt(j) == str.charAt(i),所以j++,T[i] = j = 2;

⑤部分串 "ABABA" 在④的基础上加了一个字符"A", 此时i = 4, j = 2; 判断出str.charAt(j) == str.charAt(i),所以j++,T[i] = j = 3;

⑥部分串 "ABABAA" 在⑤的基础上加了一个字符"A", 此时i = 5, j = 3 判断出str.charAt(j) != str.charAt(i),取上一个表项的值,也就是 j 对应的字符"B"前边"ABA" 的匹配值,也就是取③中匹配出来的值 j = T[j -1] = T[2] = 1, 此时while条件成立,str.charAt(j) != str.charAt(i),继续取之前匹配的值 j = T[j -1] = T[0] = 0,判断出 str.charAt(j) == str.charAt(i),所以j++, T[i] = j = 1;

⑦部分串 "ABABAAA" 在⑥的基础上加了一个字符"A", 此时i = 6, j = 1; 循环判断出str.charAt(j) != str.charAt(i),继续取之前匹配的值 j = T[j -1] = T[0] = 0,判断出 str.charAt(j) == str.charAt(i),所以j++, T[i] = j = 1;

⑧部分串 "ABABAAAB" 在⑦的基础上加了一个字符"B", 此时i = 7, j = 1 判断出str.charAt(j) == str.charAt(i),所以j++,T[i] = j = 2;

⑨部分串 "ABABAAABA" 在⑧的基础上加了一个字符"A", 此时i = 8, j = 2 判断出

str.charAt(j) == str.charAt(i),所以j++,T[i] = j = 3;

最后得到部分匹配表:T = [0, 0, 1, 2, 3, 1, 1, 2, 3];

总结

部分匹配表的生成可以分为两部分,一是在原有的基础上累加,例如③④⑤,是在原有基础上进行的最大长度匹配;如果字符不相等,则取上一个表项中的值,也就是第0位到第 j - 1 位字符的最大长度,查找过程与动态规划类似。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值