《大话数据结构》----串-----String字符串匹配算法---KMP算法和求next数组(四种求法)---附书本和网上资料不一样的区别

二更: 理解学会以后,感觉写的好垃圾,翻翻最下面资料吧还不错.


kmp算法

可以说目前耗时较长,比较晦涩难以吸收的算法,介绍我就不多说了
文中是自己的学习过程中资料合集
可以翻最最后各种资料进行资料套娃.

说说重点区别

若是没有对照<<大话数据结构>>,可看一眼第4.5点

简单说: 书本和网上公式不同造成的求法不同,从而结果不同,最后配套使用,最好理解到家.

这个区别在代码前面,才能好好敲代码,毕竟不可能只看一本书就能看懂KMP,然后查阅资料至少对照了五组算法资料,终于有帖子附资料,发现其中的不同

  1. <大话数据结构> 中的算法我对照书籍在使用上有一点点区别.书中next数组声明了255长度(p114倒数第四行),若是new int[str.toCharArray().length]长度的话,就会溢出,你可以+1长度

  2. 书中的算出来next[]所有基础都是j=1的情况下.故第一个例子中abcdex,对照了j=1next[1]=0next[2]=1…的数组,其实真实next[7]={0,0,1,1,1,1,1}注意第一个next[0],而往往网上资料,都会输出0 0 1 1 1 1 1,造成结果感觉总是差一位,初学者不要怀疑自己.
    《大话数据结构》----串-----String字符串匹配算法---KMP算法和求next数组(四种求法)---附书本和网上资料不一样的区别_第1张图片

  3. 在看视频1(<–这个1可以点)时,更能加深上面一点,<<大话数据结构>>子串(模式串)下标从1开始存的!!!,第0位没用到,所有的例子都是j=1开始,造成你从网上拿到资料,总感觉和书上对不上

  4. 接着上一点,还有一点对不上,数字都对不上呢.因为真的是公式不同
    在KMP算法讲解(next数组求解中)使用的公式是:
    公式1
    而书中的资料公式是
    公式2
    这样同样的模式串算出来的结果是-1 0 0 0 00 1 1 1 1 1
    可以先区分出来你看的资料是多少,然后再说对不对.

  5. 不算区别,算强调吧.注意知识点,就是前缀后缀最长公共元素长度next数组 不一样.导致也浪费了一些时间

求next[]代码

因为搜索了理解前期搜索了很多资料,在此集合一下next不同求法
我这里四种求法只是搬运工,配套使用 配套使用 配套使用

package com.company;

/**
 * @Author: comfort
 * @Date: 2020/8/5
 */
public class StringTest {

    public static void main(String[] args) {
        String source = "ABCDABD";
        int[] ints;
        System.out.println("暴力匹配O(m^3)前后缀");
        ints = KMPArray(source);
        for (int anInt : ints) {
            System.out.print(anInt+"  ");
        }
        System.out.println("\n时间复杂度O(p*k)?");
        ints = getNext5(source);
        for (int anInt : ints) {
            System.out.print(anInt+"  ");
        }

		//这个没做出来,可能转JAVA哪里没对上算出来的不对
        System.out.println("\n<<大话数据结构>>中算法,下标0 不计入");
        ints = getNext3(source);
        for (int anInt : ints) {
            System.out.print(anInt+"  ");
        }
        System.out.println("\n 使用-1公式");
        ints = getNext4(source);
        for (int anInt : ints) {
            System.out.print(anInt+"  ");
        }
    }

    /**
     * KMP算法讲解(next数组求解)
     * https://blog.csdn.net/qq_37174526/article/details/90141833
     */
    public static int[] KMPArray(String lookup){
        int length = lookup.length();
        char[] chars = lookup.toCharArray();
        int[] next = new int[chars.length];
        next[0]=-1;
        next[1]=0;
        for (int i = 2; i<length; i++) {
            //最长长度
            int maxLen =i-1;
            int len,j;
            //从后缀查起来
            for ( len = maxLen ; len >= 1; len--) {
                //从前缀开始
                for ( j = 0; j < len; j++) {
                    if (chars[j] != chars[j + i - len]) {
                        break;
                    }
                }
                if (j == len) {
                    next[i]=len;
                    break;
                }
            }
            if (len < 1) {
                next[i]=0;
            }
        }
        return next;
    }

    /**
     * 字符串匹配的KMP算法
     * https://blog.csdn.net/qq_41730082/article/details/83350315
     */
    public static int[] getNext5(String string) {
        int len = string.length();
        char[] str = string.toCharArray();
        int[] next = new int[len];
        next[0] = -1;
        int k = -1;
        //基础待查字符串的长度
        for(int q=1; q<=len-1; q++)
        {
            //K+1从0开始,Ks初始化为-1的原因
            //如果第K+1位与目前遍历这位相等,我们就继续往下走,不然就要向前回溯了
            while(k>-1 && str[k+1]!=str[q])
            {
                //向前回溯
                k = next[k];
            }
            //如果经过前面判断后的下一位与目前的这位相等,那么就将K推到K+1
            if(str[k+1] == str[q])
            {
                k++;
            }
            //给予next[]数组赋予对应的值
            next[q]=k;
        }
        return next;
    }
    /**
     *   KMP字符串模式匹配算法Java实现
     *   http://www.voidcn.com/article/p-uiblkjbk-bpu.html
     */

    protected static int[] getNext4(String s) {
        // 已知next[j] = k,利用递归的思想求出next[j+1]的值
        // 如果已知next[j] = k,如何求出next[j+1]呢?具体算法如下:
        // 1. 如果p[j] = p[k], 则next[j+1] = next[k] + 1;
        // 2. 如果p[j] != p[k], 则令k=next[k],如果此时p[j]==p[k],则next[j+1]=k+1,
        // 如果不相等,则继续递归前缀索引,令 k=next[k],继续判断,直至k=-1(即k=next[0])或者p[j]=p[k]为止
        char[] p = s.toCharArray();
        int pLen = p.length;
        int[] next = new int[pLen];
        int k = -1;
        int j = 0;
        // next数组中next[0]为-1
        next[0] = -1;
        while (j < pLen - 1) {
            if (k == -1 || p[j] == p[k]) {
                k++;
                j++;
                next[j] = k;
            } else {
                k = next[k];
            }
        }
        return next;
    }

    /**
     * <<大话数据结构>>中算法
     * 总觉得哪里不对...
     */
    public static int[] getNext3(String str) {
        char[] chars = str.toCharArray();
        //记得长度+1
        int[] next = new int[chars.length+1];
        int i=1;
        int j=0;
        next[1]=0;
        while (i < chars.length) {
            if (j == 0 || chars[i] == chars[j]) {
                ++j;
                ++i;
                next[i]=j;
            }else{
                j = next[j];
            }
        }
        return next;
    }

}

当然输出也是不一样的

暴力匹配O(m^3)前后缀
-1  0  0  0  0  1  2  
时间复杂度O(p*k)?
-1  -1  -1  -1  0  1  -1  
<<大话数据结构>>中算法,下标0 不计入
//书中的转java失败,暂时不要使用.
0  0  1  1  1  1  2  1  
 使用-1公式
-1  0  0  0  0  1  2  

看着都不一样,后续还有配合kmp算法一起食用,
我感觉答案应该还得+1,因为 KMP算法计算next函数值(教材版,超简单!) 看了这个视频

唉…书中的算法照着抄都没做出来,可能C和java哪里不一样,比较失败.希望大佬告诉我.

我自己用的KMP字符串模式匹配算法Java实现(这篇也是转载别人的.也可以进行资料套娃…)实现的,大家看着来一套.


关于这几个资料的翻阅或者翻阅资料的收获

  1. 读资料独立思考,理解晦涩,但是有收获零碎知识收获
  2. 其次看视频,结合资料零碎知识可以迅速组织成知识树(看视频恍然大悟.)
  3. 重在理解,还需巩固.最好默写.

参考资料

文章:

  • 大概知道next数组怎么算和怎么回事:
    数据结构与算法之美笔记: 字符串匹配 「BF 算法、RK 算法、BM 算法、KMP 算法」
  • 深入浅出,获取next[]从暴力遍历O(m^3)再次优化O(m)
    KMP算法求解(next数组求解)
  • 逐步讲解数组一步步优化,增加在next数组上再次改进
    KMP字符串模式匹配算法Java实现
  • 详细,最重要的文中引用了大量文献,可以引用套娃(滑稽)
    从头到尾彻底理解KMP
  • 包含了拓展习题,先make一下.
    字符串匹配的KMP算法

视频:

  • 大概知道next数组可以这么简单算出来,好像很简单样子:
    KMP算法计算next函数值(教材版,超简单!)
  • 巨卜木曹,原来是这么来用的,但是-1和0那边以及计算欠缺点:
    天勤公开课」KMP算法易懂版
  • 嗯,舒服了,介绍prm数组和next数组,补充了上一个视频中的-1和0,还有next数组生成过程中,前缀后缀在匹配中动画演示,最后还附加了c++和php的代码
    【算法ABC × Manim】KMP算法 - 拒绝做暴力字符串匹配的受害者

  1. 天勤公开课」KMP算法易懂版 ↩︎

你可能感兴趣的:(数据结构)