ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

KMP算法

2021-05-19 11:36:34  阅读:156  来源: 互联网

标签:匹配 charAt dest str2 str1 next 算法 KMP


KMP算法

1.KMP算法的应用场景:字符串匹配问题。

假设str1 = BBC ABCBAB ABCDABCDABDE, str2 = ABCDABD,然后判断str1是否还有str2,如果存在,就返回第一次出现的位置 ,如果没有返回-1。

解法1:暴力匹配算法

假设str1匹配到i位置,字串str2匹配到j位置,则

1)如果当前匹配成功(即str[i] = str[j]),则i++, j++,继续匹配下一个字符。

2)如果匹配不成功(即str[i]!=str[j]),令i = i-j+1(i回到开始匹配的字符的后一个位置), j = 0(回到初始位置),相当于每次匹配失败,i回溯,j重置。

由此可以看出暴力匹配方法会有大量回溯,浪费大量时间,不可行。

2.KMP算法介绍

1)KMP算法是一个解决模式串在文本串是否出现过,如果出现过,返回最早出现的位置的经典算法。

2)部分匹配表产生

字符串:“bread”; 前缀: b, br, bre, bred 后缀:read, ead, ad, d

部分匹配值就是前缀和后缀的最长的共有元素的长度,以“ABCDABD”为例:

“A”的前缀和后缀都为空集,所以共有元素的长度为0。

“AB”的前缀为[A],后缀为[B],共有长度为0。

“ABC”的前缀[A,AB], 后缀为[BC,C],共有长度为0。

"ABCD"的前缀[A,AB,ABC],后缀为[BCD,CD,D],共有长度为0。

“ABCDA”的前缀[A,AB,ABC,ADCD],后缀为[BCDA,CDA,DA,A],共有元素为“A”,所以共有长度为1;

“ABCDAB”的前缀[A,AB,ABC,ABCD,ABCDA],后缀[BCDAB,CDAB,DAB,AB,B],共有元素为“AB”,所以共有长度为2;

“ABCDABD”的前缀[A,AB,ABC,ABCD,ABCDA,ABCDAB],后缀[BCDABD,CDABD,DABD,ABD,BD,D],共有长度为0;

由上可得出部分匹配表为

搜索词 A B C D A B D
部分匹配值 0 0 0 0 1 1 0

解法2 :

package com.ll.kmp;

public class KMPAlgorithm {
    public static void main(String[] args) {
        String str1 = "BBC ABCDAB ABCDABCDABDE";
        String str2 = "ABCDABD";
        int[] next = kmpNext(str2);
        System.out.print(kmpSearch(str1, str2, next));

    }

    /**
     * kmp匹配算法
     *
     * @param str1 源字符串
     * @param str2 目标字符串
     * @param next 部分匹配表
     * @return 返回对应位置,未找到返回-1
     */
    public static int kmpSearch(String str1, String str2, int[] next) {

        for (int i = 0, j = 0; i < str1.length(); i++) {
            // 需要处理str1.charAt(i) != str2.charAt(j),去调整j的大小
            while (j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j = next[j - 1];
            }
            // 字符匹配成功
            if (str1.charAt(i) == str2.charAt(j)) {
                j++;
            }
            if (j == str2.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }

    /**
     * 获取字符串的部分匹配表
     *
     * @param dest 目标字符串
     * @return
     */
    public static int[] kmpNext(String dest) {
        // 创建部分匹配表
        int[] next = new int[dest.length()];
        next[0] = 0;  // 如果字符串长度位1, 部分匹配值为0;
        for (int i = 1, j = 0; i < dest.length(); i++) {

            while (j > 0 && dest.charAt(i) != dest.charAt(j)) {
                j = next[j - 1];
            }

            // 如dest.charAt(i) == dest.charAt(j),则部分匹配值j++
            if (dest.charAt(i) == dest.charAt(j)) {
                j++;
            }
            next[i] = j;
        }
        return next;
    }
}

标签:匹配,charAt,dest,str2,str1,next,算法,KMP
来源: https://www.cnblogs.com/cqyp/p/14783839.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有