KMP算法, 什么是KMP算法 ,暴力匹配 ,KMP算法实现

15 篇文章 0 订阅

KMP算法

什么是KMP算法

KMPKnuth、Morris和Pratt首字母的缩写,KMP也是由这三位学者发明(1977年联合发表论文)。

KMP主要应用在字符串的匹配,是一个解决模式串在文本串是否出现过,如果出现过,得出最早出现的位置的经典算法。其主要思想是:当出现字符串不匹配时,可以知道之前已经匹配的文本内容,可以利用这些信息避免从头再去匹配,从而提高匹配效率。

因此如何记录已经匹配的文本内容,才是KMP的重点~这也使得next数组派上了用场。

KMP算法就利用之前判断过信息,通过一个 next 数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过 next 数组找到前面匹配过的位置,省去了大量的计算时间。

在这里插入图片描述

暴力匹配

现给出一段字符串str1:“硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好”,和一段子字符串str2:“尚硅谷你”。

要求写出判断str1是否含有str2的代码,如果存在就返回第一次出现的位置,如果没有则返回-1。

说到字符串匹配,我们第一时间想到的是直接遍历字符串,看看是否存在。这种方法称为暴力匹配,抛开效率不说,这种方式是最直接,最简单的方式。

然而暴力匹配也是一种算法,一种解决方案,针对上述问题,我们可以得出暴力匹配算法的思路(假设现在 str1 匹配到 i 位置,子串 str2 匹配到 j 位置):

  • 如果当前字符匹配成功(即 str1[i] == str2[j]),则 i++,j++,继续匹配下一个字符
  • 如果失配(即 str1[i] != str2[j]),令 i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为 0
  • 用暴力方法解决的话就会有大量的回溯,每次只移动一位,若是不匹配,移动到下一位接着判断,浪费了大量的时间(不可行!)

代码示例:

/**
 * 暴力匹配算法
 * @param str1
 * @param str2
 * @return 返回str2首次出现在str1的位置,匹配不到则返回-1
 */
public static int violenceMatch(String str1, String str2) {
    char[] s1 = str1.toCharArray();
    char[] s2 = str2.toCharArray();

    int i = 0; // 指向s1
    int j = 0; // 指向s2

    while (i < s1.length && j < s2.length) {
        if (s1[i] == s2[j]) {
            i++;
            j++;
        } else {
            // 只要有一个没有匹配上
            i = i - (j - 1);
            j = 0;
        }
    }
    // 判断是否匹配成功
    if (j == s2.length) {
        return i - j;
    }
    return -1;
}

main方法中测试暴力匹配:

public class AlgorithmUtils {
    public static void main(String[] args) {
        String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
        String str2 = "尚硅谷你";

        int index = AlgorithmUtils.violenceMatch(str1, str2);
        if (index != -1) {
            System.out.printf("第一次出现的位置是%d", index);
        }
    }
}

KMP算法实现

前面呢我们已经使用暴力匹配算法,完成了上述问题的求解!也知道了暴力匹配存在效率问题,那么KMP算法又是怎样实现呢?

为方便阐述,这里我们换个案例:现有两组字符串

str1 = “BBC ABCDAB ABCDABCDABDE”;
str2 = “ABCDABD”;

要求使用 KMP算法 完成判断,str1 是否含有 str2,如果存在,就返回第一次出现的位置,如果没有,则返回-1。

备注:不能使用简单的暴力匹配算法!!!

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

皮皮攻城狮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值