串的匹配模式算法<KMP>(Java语言代码)

KMP算法(Knuth-Morris-Pratt算法)是由Donald Knuth、James H. Morris Jr. 和Vaughan Pratt三人共同提出的,因此得名。这是一种改进的字符串匹配算法,旨在高效地解决在一个文本串(主串)中查找一个模式串(子串)出现的位置的问题。与朴素的暴力匹配算法相比,KMP算法的关键优势在于它能够利用已经得到的匹配信息,避免在发生不匹配时重新检查文本串中已经比较过的字符,从而减少了不必要的比较,提高了搜索效率。

算法核心:

KMP算法的核心在于构建一个“部分匹配表”(也称为“失配表”或“前缀后缀表”),通常称为next数组。next数组记录了模式串中每个位置前面的子串中,有多大长度的真前缀等于其对应的真后缀。这里的真前缀是指不包括整个子串本身的前缀,真后缀同理。next数组的构建基于这样一个事实:如果模式串中的某个前缀等于某个后缀,那么当这个前缀与文本串中的相应部分匹配失败时,模式串可以直接跳过这两个相等的部分继续比较,而无需回溯文本串的指针。

KMP算法步骤:

  1. 预处理:首先根据模式串构建next数组。next[j]表示当模式串的前j个字符与文本串匹配失败时,模式串应该跳转到哪个位置继续比较以避免重复比较。

  2. 匹配过程:然后开始在文本串中进行匹配。初始时,主串和模式串的指针都指向各自的起始位置。如果当前字符匹配成功,则两个指针都向前移动;如果不匹配,模式串的指针根据next数组的值来决定跳转的位置,而主串的指针保持不变。

  3. 终止条件:当模式串的最后一个字符与文本串中的某个字符匹配成功时,说明找到了一个匹配的位置。此时可以返回该位置作为匹配成功的起始索引。如果模式串的指针移动到其末尾,则匹配完成;否则,继续进行比较。

KMP算法的时间复杂度为O(n + m),其中n是文本串的长度,m是模式串的长度,这使得它在处理长文本和模式串时尤其高效。

完整代码:

//串的匹配模式算法--KMP
public class KMP {
    // kmp函数
    // S 主串
    // T 模式串
    // next next数组
    public static int kmp(String S, String T, int[] next) {
        int i = 0, j = 0;
        while (i < S.length() && j < T.length()) {
            if (j == -1 || S.charAt(i) == T.charAt(j)) {
                ++i;
                ++j;
            } else {
                j = next[j];
            }
        }
        if (j >= T.length()) {
            return i - T.length();
        } else
            return 0;
    }

    // 获取next数组函数
    // T 模式串
    // next next数组
    public static void get_next(String T, int[] next) {
        int i = 2, j = 0;
        next[0] = -1;
        next[1] = 0;
        while (i < T.length()) {
            if (j == -1 || T.charAt(i - 1) == T.charAt(j)) {
                next[i] = j + 1;
                ++j;
                ++i;
            } else {
                j = next[j];
            }
        }
    }

    public static void main(String[] args) {
        String t = "abcac";// 模式串
        String s = "ababcabcacbab";// 主串
        int[] next = new int[t.length()];
        get_next(t, next);// 获取next数组
        System.out.println(kmp(s, t, next));
    }
}

 

 运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿杰_Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值