关于KMP算法的思考

KMP算法解决的问题

假设主串为S,待比较的子串为s:

朴素匹配算法:如果使用朴素匹配算法,s和S每个字符逐一比较,如果有一个字符不相同,则s的下标和S的下标都会重新退回到0,再次进行比较。

KMP算法:KMP算法就是为了子串s能够快速的移动,不要从0开始比较。

KMP算法的依据

子串s能够快速移动的依据就是已匹配的子串的前n位能否等于匹配部分的主串的后n位。如果相同,则可以跳过中间部分,从这一相同的部分再次开始比较。

KMP算法的过程

举个栗子:

  假如现在S和s如下:

                  主串S:xxxxABDBABxxxxx
                  子串s:ABDBACF
  开始比较:

                          xxxxABDBABxxxxx
                              ABDBABF

1. 寻找匹配串:

我们可以发现,已匹配的子串s为:ABDBAB,匹配部分的主串S:ABDBAB

2. 分析前缀后缀

前缀:A AB ABD ABDB ABDBA
后缀:B AB BAB DBAB BDBAB

3. 找最大并且相同的前后缀

我们可以发现,AB为最大相同的前后缀

4. 跳过中间部分:

移动的距离为匹配的长度-刚才的前后缀长度
也就是 6-2=4

                          xxxxABDBABxxxxxxxxxx
                                    ABDBABF

KMP算法的实现

 //寻找回溯的下标
    public static int[] find_next(char[] s){
        int i = 0;                              //记录遍历字符串的下标,从0开始遍历
        int j = -1;                             //记录最大前后缀的下标,还没有开始匹配
        int[] next = new int[s.length+1];       //保存下标
        next[0] = -1;                           //初始化数组,子串中没有相同的字符
        while (i<s.length)
        {
            if(j == -1 || s[i] == s[j])         //找到匹配字符的最大前后缀,下标继续向前找
            {
                ++i;
                ++j;
                next[i] = j;
            }
            else                               //没有找到,开始回溯查找
                j = next[j];
        }
        return next;
    }


    //KMP匹配算法
    public static int index(char[] parent,char[] children,int[] next){
        int index = -1;                 //记录子串匹配父串的索引
        int plen = parent.length;
        int clen = children.length;
        int i = 0;                      //记录遍历主串的下标
        int j = -1;                     //记录子串需要回溯的下标
        while (i < plen && j <clen)
        {
            if(j == -1 || parent[i]==children[j])       //匹配字符成功
            {
                ++i;
                ++j;
            }
            else                        //匹配失败,根据next[]回溯
                j = next[j];
        }
        if(j>=clen)                     //完全匹配成功
            index = i-clen;
        return index;
    }

测试一下:

 public static void main(String[] args) {
        String parent = "xABDBAxxABDBABxxxxx";
        String children = "ABDBAB";
        int[] next = find_next(children.toCharArray());
        int index = index(parent.toCharArray(),children.toCharArray(),find_next(children.toCharArray()));
        System.out.println(index);
    }

结果为8

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值