字符串匹配之KMP算法

KMP算法的难点在于next数组和前缀表
KMP算法流程:

  • 假设现在文本串 S 匹配到 i 位置,模式串 P 匹配到 j 位置
  • 如果 j = -1,或者当前字符匹配成功(即 S[i] == P[j] ),都令 i++,j++,继续匹配下一个字符;
  • 如果 j != -1,且当前字符匹配失败(即 S[i] != P[j] ),则令 i 不变,j = next[j]。此举意味着失配时,模式串 P相对于文本串 S 向右移动了 j - next [j] 位
    换言之,将模式串 P 失配位置的 next 数组的值对应的模式串 P 的索引位置移动到失配处
    在这里插入图片描述
    在这里插入图片描述
    首先,列出模式串 P 的所有子串:
    在这里插入图片描述

然后,求得每一个子串的所有前缀与后缀。

前缀 指除了最后一个字符以外,一个字符串的全部头部组合;后缀 指除了第一个字符以外,一个字符串的全部尾部组合。

以子串abaab为例:
在这里插入图片描述
因此,它的前缀后缀的公共元素的最大长度为 2

求得原模式串 P 的子串对应的各个前缀后缀的公共元素的 最大长度表 下图。
在这里插入图片描述
根据最大长度表 去求 next 数组:next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。
在这里插入图片描述
在这里插入图片描述
Java实现

private int[] getNext(String p) {
        int M = p.length();
        int[] next = new int[M];
        next[0] = -1;
        int j = 0;
        int k = -1;
        while (j < M - 1) {
            if (k == -1 || p.charAt(k) == p.charAt(j)) {
                next[++j] = ++k;
            } else {
                k = next[k];
            }
        }
        return next;
    }
    int KmpSearch(String p, String t) {
        // 根据模式字符串获得next数组
        int[] next = getNext(p);
        int N = t.length();
        int M = p.length();
        int i = 0;
        int j = 0;
        while (i < N && j < M) {
            if (j == -1 || p.charAt(j) == t.charAt(i)) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
        if (j == M) {
            return i - j;
        } else {
            return -1;
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值