数据结构之KMP算法


前言

本篇博客主要记录数据结构之KMP算法,通过举例来说明暴力匹配和KMP的不同。

一、问题解析

举个例子,如果给定文本串S“BBC ABCDAB ABCDABCDABDE”,和模式串P“ABCDABD”,现在要拿模式串P去跟文本串S匹配。

现将两种思路分析如下:

(1)暴力匹配
在这里插入图片描述
(2)KMP算法思路
在这里插入图片描述

二、代码测试

1.暴力破解

代码如下(示例):

/**
     * 暴力匹配算法
     * @param str1 原字符串
     * @param str2  要匹配的字符串
     * @return 思路:
     *              1.如果当前字符匹配成功,则i++,j++,继续匹配下一个字符
     *              2.如果匹配失败,令 i = i-(j-1),j=0 相当于每次匹配失败时,i回溯,j被置为0
     */
    public static int violenceMatch(String str1, String str2) {
    
    
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();

        int s1Len = s1.length;
        int s2Len = s2.length;

        //索引i指向s1
        int i = 0;
        //索引j指向s2
        int j = 0;
        while (i < s1Len && j < s2Len) {
    
    
            if (s1[i] == s2[j]) {
    
    
                //匹配成功
                i++;
                j++;
            } else {
    
    
                //匹配不成功
                //如果匹配失败(s1[i]!=s2[j].令i=i-(j-1),j=0)
                i = i - (j - 1);
                j = 0;
            }
        }
        //判断是否匹配成功
        if (j == s2Len) {
    
    
            return i - j;
        } else {
    
    
            return -1;
        }
    }

2.KMP代码

代码如下(示例):
使用KMP算法需要先得到字符串的匹配值表,代码中为next数组。具体求法如下图:
在这里插入图片描述
步骤:
1.先得到字符子串的部分匹配表;
2.使用部分匹配表完成KMP匹配。

/**
     * 获取到一个字符串的部分匹配值
     */
    public static int[] kmpNext(String dest) {
    
    
        //创建next数组,保存部分匹配值
        int[] next = new int[dest.length()];
        //如果字符串长度为1,那么部分匹配值就是0
        next[0] = 0;
        for (int i = 1, j = 0; i < dest.length(); i++) {
    
    
            //当dest.charAt(i) != dest.charAt(j),我们需要从next[j-1]获取新的j
            //直到满足dest.charAt(i) == dest.charAt(j)才退出。
            //这是temp算法的一个核心点
            while (j > 0 && dest.charAt(i) != dest.charAt(j)) {
    
    
                j = next[j - 1];
            }
            //当dest.charAt(i) == dest.charAt(j)条件满足时,部分匹配值就需要加一,放入数组
            if (dest.charAt(i) == dest.charAt(j)) {
    
    
                j++;
            }
            next[i] = j;
        }
        return next;
    }


    /**
     * KMP搜索算法
     * 没有匹配到就返回-1,匹配到就返回第一个匹配的位置
     */
    public static int KMPSearch(String str1, String str2, int[] next) {
    
    
        //遍历str1
        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;
    }

猜你喜欢

转载自blog.csdn.net/z318913/article/details/120827134
今日推荐