数据结构与算法(十五)KMP算法

KMP算法原理:

在这里插入图片描述
当下标为5的字符不匹配时, 因为知道前五个字符的前缀A A 和后缀A A其实是一样的, 所以直接从模式串的第三位开始比较,不用回溯到开始的下一位,减少比较的次数。

在这里插入图片描述
在这里插入图片描述
怎么知道将模式串移动到哪个位置呢?就需要借助前缀后缀表(部分匹配表), 前缀表记录了字符串前后缀最大相等的值的长度

对于模式串 AABAAD

  • A 没有前后缀 -> 0
  • AA 前缀 A 后缀 A, 最大相等值A,长度为1 -> 1
  • AAB 前缀 A, AA; 后缀B, AB,没有相等的值 -> 0
  • AABA 前缀A, AA, AAB; 后缀A, BA, ABA 最大相等值A,长度为1 ->1
  • AABAA 前缀A, AA, AAB, AABA; 后缀A, AA, BAA, ABAA, 最大相等值AA, 长度为2 ->2
  • AABAAD 前缀A, AA, AAB, AABA, AABAA; 后缀D, AD, AAD, BAAD, ABAAD, 没有最大相等值 -> 0

由此得到部分匹配表
在这里插入图片描述

生成部分匹配表代码

private static int[] generatePrefix(String search) {
        char[] searchChar = search.toCharArray();
        int[] prefix = new int[(searchChar.length)];
        //第一位字符,前后缀公共部分为0
        prefix[0] = 0;
        //i指向后缀末尾, j指向前缀末尾
        for (int i = 1, j = 0; i < searchChar.length; i++) {
            while (j > 0 && searchChar[i] != searchChar[j]) {
                j = kmpTprefixable[j - 1];//
            }

            if (searchChar[i] == searchChar[j]) {
                j++;
            }

            prefix[i] = j;
        }
        return prefix;
    }

实现下图的模式串右移,意味着将指向模式串的指针从 “D” 移动到第三位 “B”(下标为2), 也就是上面匹配表中“D”的前一位 “A”对应的值
在这里插入图片描述

用java代码实现匹配

private static int KMPSearch(String source, String search, int[] prefix) {
        for (int i = 0, j = 0; i < source.length(); i++) {
            while (j > 0 && source.charAt(i) != search.charAt(j)) {
                j = prefix[j - 1];//回溯到模式串前缀和后缀相等的位置
            }

            if (source.charAt(i) == search.charAt(j)) {
                j++;
            }

            if (j == search.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值