java数据结构与算法基础-----字符串------KMP算法

Java编程:KMP算法 ”ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。-”ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;-”ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1; 阅读详情
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.youkuaiyun.com/grd_java/article/details/123063846

一、概述

什么是KMP算法
  1. 我们拿LeetCode28题为例,暴力解法时间复杂度O(m*n), 而KMP算法时间复杂度O(n + m),空间复杂度O(m),所以,KMP算法是一个提升字符串匹配效率很好的一个算法。但是我们要注意一点,不同的环境和不同的编程语言,KMP的效率未必好过其它的算法,例如优化后的BM算法拥有比KMP更好的平均时间复杂度(注意是平均时间复杂度更好,算法本身理论上的时间复杂度,KMP更好)
  1. 暴力解法的效率
    在这里插入图片描述
  2. KMP的效率提升
    在这里插入图片描述
  1. 上面这道28题,仅仅说明,在这道题所规定的场景下,KMP确实发挥出了它应有的实力。但是在实际工作场景中,有时候会遇到种种不太适配的场景,这些时候KMP的表现也确实会受到多方面的影响,从而导致综合下来看,此时其它算法的表现更加优秀。

KMP算法很难,如果拿下,可以很好的提升你的编程思维,但是实际工作中也确实很少有场景会使用到它。不过,虽然完整的KMP算法不常用,但是如果单拿出它其中某一个步骤的思想,却往往能在很多不同的场景中,发挥奇效。

总结起来就是,很多问题,其实只需要使用KMP算法中的某一个步骤的思想就可以很好的解决并提高效率。但是如果你只记住了代码,每次使用KMP都必须把完整代码写出来使用的话,就会陷入杀鸡焉用牛刀的困境,造成不必要的时间和空间上的浪费。

KMP的简单概括,以及暴力解法的不足
  1. KMP算法:重复出现的,不要重复比较,跳过它。如何实现这个效果呢?只需要使用一个数组来记录重复出现的次数。
  1. 解决模式串在文本串是否出现过,如果出现过,获取最早出现的位置的经典算法
  2. 常用于在一个文本串S内查找一个模式串P出现的位置,此算法由Donald Knuth、Vaughan Pratt、James H.Morris三人于1977年联合发表,故取三人姓氏命名此算法为Knuth-Morris-Pratt,简称KMP算法
  3. 利用之前判断过的信息,通过一个next数组,保存模式串中前后最常公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去大量计算时间
  1. 暴力匹配存在的问题:例如ABCDABEABCDABD 匹配 ABCDABD
  1. ABCDABEABCDABD从头匹配子串ABCDABD,可以发现最后一个字母D不匹配E,也就是说ABCDABE 这个串 肯定不匹配ABCDABD
  2. 但是在未知的情况下,我们无法像人脑一样,知道这个串匹配不了,从而向后移一位,从E开始继续观察是否匹配,比如:后面的EABCDABD继续匹配子串ABCDABD, 此时我们发现E不匹配,再次向后移一位进行ABCDABD匹配ABCDABD ,此时发现成功匹配了。但是计算机可不像我们人脑一样,可以进行这样的思考。
  3. 所以暴力匹配中,我们不确定是否后移一位就匹配了,因此,只能一个个后移比较
  1. 暴力匹配哪里可以优化呢?
  1. 我们先看简单的匹配:ABCDABE和ABCDABD发现E和D不匹配,使用暴力解法,需要后移,将剩余的BCDABE再次匹配ABCDABD
  2. 此时,我们发现,又不匹配,如果我们想要匹配,最起码应该A开头吧,也就是说,再往后面移动,也没用,直到下一个A开头的
  3. 但是计算机不是人,使用暴力解法,还是会按部就班的继续匹配。例如接下来它会用CDABE匹配 ABCDABD,然后又发现不匹配,再次进行DABE匹配 ABCDABD… 以此类推
  4. 那么我们可以发现,BCD这三个开头,已经确定不匹配,没必要重复匹配,应该跳过,直接匹配下一个A。例如:直接跳到ABE匹配 ABCDABD

二、KMP思想

各位注意KMP解决的最大的问题是:假设我们匹配时,发现匹配到某个字符匹配不下去了,此时我们究竟是将已匹配的字符全部直接跳过,还是说只能跳过一部分。

  1. 例如:ABABABD匹配ABABD,从头匹配时,我们发现红色的位置是匹配不上的
  2. 如果我们全部跳过,就只剩下BD匹配ABABD,显然不正确
  3. 此时我们应该跳过字符串ABABABD中前面两个标红的AB,进行剩下的ABABD匹配ABABD。此时成功匹配。
KMP的解决思路:例如ABCDABEABCDABD 匹配 ABCDABD
  1. 对匹配串进行处理。我们先对ABCDABD这个子串做文章,判断匹配串某个位置不匹配时,应该怎么跳过,最终存储到next数组中。
  1. ABCDABE匹配ABCDABD,如果到D不匹配,应该直接变成ABE匹配ABCDABD,因为我们要找到下一个AB开头的
  2. 再比如ABCDEFGTTTTT匹配ABCDABD,如果第一次到E不匹配,应该直接变成EFGTTTTT匹配ABCDEFG,因为前面的ABCD全部不匹配,直接跳过
  3. 总结一下,可以发现,ABCDABD这个子串,出现两次AB,那么如果一直匹配到ABCDABD才发现不对,就应该直接跳到后面的AB继续匹配
  4. 而如果没有匹配到出现重复字符,比如匹配到ABCD就发现不对了,那么就应该直接跳过ABCD
  1. Next数组,如何记录,如何生成数组:是否有重复缀,应该用一个数组记录。比如ABCDABD对应数组应该是[0,0,0,0,1,2,0],代表A重复,长度1,AB重复,长度为2. 这是怎么算出来的呢?-----用前缀,后缀共同匹配法,就是从左到右,依次把前几个字母所组成的字符串列出来,然后再将前缀和后缀列出来,看看前后缀共同拥有的元素长度
  1. A的前后缀都是空集,前后缀共有0
  2. AB前缀A,后缀B,共有0
  3. ABC前缀A,AB。后缀BC,C,共有0
  4. ABCD前缀A,AB,ABC,后缀BCD,CD,D,共有0
  5. ABCDA前缀A,AB,ABC,ABCD,后缀BCDA,CDA,DA,A,共有A,长度1
  6. ABCDAB前缀A,AB,ABC,ABCD,ABCDA,后缀BCDAB,CDAB,DAB,AB,B,共有AB,长度2
  7. ABCDABD前缀A,AB,ABC,ABCD,ABCDA,ABCDAB,ABCDABD后缀BCDABD,CDABD,DABD,ABD,BD,共有0
  1. 如何利用数组,跳过该跳过的:ABCDABCABCDABD 匹配ABCDABD,前面我们已经得出Next数组为:[0,0,0,0,1,2,0]
  1. ABCDABCABCDABD 匹配ABCDABD, C不匹配D,对应Next数组[0,0,0,0,1,2,0],发现是0. 也就是说,当前匹配串ABCDABD,匹配到D后不匹配了,然后Next数组记录的ABCDABD的前后缀重复缀个数为0.
  2. 这就代表着,前面已经匹配的这7个字符,没有重和部分,无需重复匹配。直接全部跳过。跳过公式为:已匹配成功字符个数-匹配不成功字符对应Next数组值。也就是7-0 = 7.
  3. 所以下一次直接跳过7个ABCDABCABCDABD(红色的为跳过的),下一次直接匹配后面的ABCDABD。也就是ABCDABD匹配ABCDABD。此时匹配成功
另一个例子

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

三、代码实现

大家可以简单浏览一下下面这个,如果不好理解,可以看再下面的多注释版本
     public int strStr(String haystack, String needle) {
        int n = haystack.length(),m = needle.length();//为了更快的速度
        if(m==0) return 0;
        //1、kmp数组
        int[] kmpArr = new int[m];
        kmpArr[0] = 0;
        for (int i = 1,j = 0; i < m; i++) {
            //"ABCDABD"
            //"i***i"两个i对应的匹配成功,那么匹配成功长度+1,j++,长度为1。说明如果匹配到ABCDA,那么下次可以把ABCD跳过,末尾的A不可以跳过
            //" i***i"然后两个i位置又成功,j++,长度为2,也就是说匹配到了ABCDAB,下次ABCD可以跳过,末尾的AB不可以,因为重复了
            //最后,j = 2,i = 6,C不匹配D
            //j = kmp[j-1] 看看后移后的缀匹配程度,一直到匹配成功,或者j = 0,从开头重新匹配
            //这个while循环,主要负责,如果当前不匹配了,是全跳过,还是只能跳过部分
            while(j>0 && needle.charAt(i)!=needle.charAt(j)) j = kmpArr[j-1];
            if(needle.charAt(i)==needle.charAt(j)) j++;//匹配成功,j长度+1
            kmpArr[i] = j;
        }
        //2、用kmp数组
        for (int i = 0,j = 0; i < n; i++) {
            //这里和上面代码一样,只不过原来是needle自己比,现在是haystack和needle比较
            while(j>0 && haystack.charAt(i)!=needle.charAt(j)) j = kmpArr[j-1];
            if(haystack.charAt(i)==needle.charAt(j)) j++;//匹配成功,j长度+1
            if(j==m) return i-j + 1;//匹配成功,返回子串起始下标
        }
        return -1;//没成功
    }
多注释版本
  1. 首先,我们需要一个数组,作为NEXT数组,表示匹配不成功后,应该跳过几个字符,进行下次匹配
    public int strStr(String haystack, String needle) {
        //先搞出kmpArr数组
        int[] kmpArr = kmpNext(needle);
        //用数组跳过没必要重复比较的
        return kmpSearch(haystack,needle,kmpArr);
    }
  1. NEXT数组:这里使用的方法是,记录当前位置匹配成功后,如果要跳,应该跳到哪里。这样的含义是,如果发现匹配到某字符匹配失败,那么证明前面都是匹配成功的,那么就访问失败字符的前一个字符的Next数组值,从而得知应该跳到哪里重新尝试匹配。例如:ABCDABD [0,0,0,0,1,2,0].C匹配失败,但是前面B匹配成功了,那么看看B成功,要跳,应该跳什么位置,我们发现Next数组中记录的是0,所以下次只能从头匹配。
  1. 首先用一个for循环,来处理从0位置开始,依次的每个子串,例如A,AB,ABC,ABCA,循环变量i代表每个子串的末尾。
  2. 然后通过while循环,来处理:如果当前的,前后缀不匹配,可以跳过几个字符。
  1. 如果匹配成功则很简单,例如:ABCDABD [0,0,0,0,1,2,0]。假设标红的下标为 i,标黄的下标为 j。我们发现标红的这个A,和开头标黄的A成功的进行了前后缀匹配。

那么我们可以让j++。它有两个作用

  1. 指向前缀的位置,也就是它在j++前,指向的就是开头的A。那么现在这个A匹配成功了,我们下个位置需要继续从A匹配吗?显然不用。下次直接尝试匹配B就好了。所以进行j++
  2. 代表当前,连续的情况下,成功匹配了多少。很明显我们现在仅仅连续匹配成功了这个标红的A。所以长度为1.
  1. 然后:ABCDABD [0,0,0,0,1,2,0]。我们发现标红的B,和开头的B成功的进行了前后缀匹配。

此时我们就可以再次进行j++;

  1. 刚刚 j 已经 =1 了。因为前面A匹配成功了,现在B也匹配成功了,那么ABCDA这个子串的前后缀,A与A匹配成功,现在末尾添加一个B,ABCDAB这个子串B与B也匹配成功了,那么代表AB与AB匹配成功了。所以下次应该匹配C
  2. A已经匹配成,然后紧跟着,B也匹配成功,所以连续情况下,连续匹配了AB,所以长度为2.
  1. 再然后:ABCDABD [0,0,0,0,1,2,0]。我们发现标红的D和标黄的C,没有成功进行匹配

也就是前缀ABC和后缀ABD没有成功匹配,我们知道KMP算法思想就是跳过没必要重复比较的。

  1. 此时如果继续比较字符更多的前后缀已经没有意义了,因为ABC和ABD已经不匹配了,接下来的ABCD,和DABD就更不行了
  2. 所以我们此时就需要考虑,是全跳呢?还是只跳一部分,然后看看剩余部分是否前后缀还能匹配
  3. 因为前面的子串如果匹配失败,应该跳到哪个位置,都已经记录在NEXT数组中了,所以直接从next数组获取即可。
  4. 既然ABC和ABD匹配失败,但是我们的NEXT数组记录的是,字符匹配成功后,应该跳跃的位置,D和C匹配失败了。但是前面的都匹配成功了,所以我们访问NEXT[ j - 1],也就是B的位置,我们想看看B匹配成功,但是我们要跳跃,应该跳到哪里去。
  5. 我们发现AB这个前缀,压根没有公共前后缀,没办法,只能全跳。也就是回到0位置继续。
  1. 再举个例子,AACDAAA[0,1,0,0,1,2,2]

AAC和AAA没有匹配成功

  1. 此时访问[0,1,0,0,1,2,2]. NEXT[ j-1 ] = 1,我们发现前缀AA如果匹配成功,下次只需要跳到1位置继续匹配即可。同时j–。
  2. 此时再次匹配,我们发现AACDAAA匹配成功,则j++,代表公共前后缀长度为2.
  1. 最后通过一个if语句来处理,是否前后缀匹配,如果匹配,记录成功匹配的字符个数。
    //第一步:获取到一个字符串(子串) 的部分匹配值表,KMP数组
    public static  int[] kmpNext(String dest) {
        //ABCDABD [0,0,0,0,1,2,0]
        int[] kmpArr = new int[dest.length()];//kmp数组,记录前后缀共同匹配长度
        kmpArr[0]=0;//单个字符,例如A的前后缀都是空集,前后缀共有0
        //i代表后缀下标,j代表前缀下标和数组对应下标
        for (int i = 1,j = 0; i < dest.length(); i++) {
            //i = 0 代表A字符,前后缀都是空串
            //i = 3 代表ABCD的D,j = 0,最前面的A
            //不相等,依然是0
            //i = 4 代表ABCDA,的A。j = 0代表最前面的A
            //前后缀相等了,但此时j = 0,说明前面没有前后缀匹配的,那么直接记录本次
            //j++ = 1 , kmpArr[4] = 1
            //i = 5 代表ABCDAB,代表后缀B,j = 1代表前缀B
            //相等了,此时j>0,并且相等,那么直接j++即可
            //j = 2,kmpArr[5] = 2
            //i = 6 代表ABCDABD,代表后缀D,j = 2代表前缀C(ABC)
            //此时j>0,并且前后不相等,那么后缀D和C不匹配,需要尝试向前匹配
            //剩下他能匹配的,也就是,A和AB,对应j是0和1
            //j = kmpArr[j-1],向前移动前缀,kmpArr[1] = 0
            //j = 0,前面没有了,判断前后缀现在是否相等
            //D 不等于 A 因此D这个后缀,没的匹配
            while(j>0&&dest.charAt(j)!=dest.charAt(i)){//如果本次前后缀不匹配
                j=kmpArr[j-1];//看看可以跳到哪里,然后继续比较是否前后缀匹配
            }
            if(dest.charAt(i)==dest.charAt(j)){//如果匹配,长度+1,
                j++;
            }
            //j 就是 长度
            kmpArr[i] = j;
        }
        return kmpArr;
    }
  1. KMP搜索:和NEXT数组逻辑几乎一样,如果遇到匹配不成功的字符,那么就考虑NEXT数组中,前一个位置匹配成功后,应该跳到哪个位置重新匹配。
    /**第二步
     * kmp搜索
     *  依然进行匹配
     *  和上面一样,j就是匹配成功的前后缀共同长度
     *  
     */
    public static int kmpSearch(String str1, String str2, int[] kmpArr) {

        //遍历
        for(int i = 0, j = 0; i < str1.length(); i++) {
            //匹配不成功就跳过
            //需要处理 str1.charAt(i) != str2.charAt(j), 去调整j的大小
            //KMP算法核心点, 可以验证...
            //String str1 = "BBC ABCDAB ABCDABCDABDE";
            //    String str2 = "ABCDABD";
            //匹配表next=[0, 0, 0, 0, 1, 2, 0]
            //当i = 10,j = 6时,前面ABCDAB都匹配成功,但是现在空格比较D,不相等,此时说明不是子串
            //此时进入循环,j = 2,比较空格和C,不相等,再进入循环
            //j = 1,比较空格和B,不相等,再进入循环
            //j = 0,条件不满足,退出循环
            //下一次,将从空格后面继续匹配,避免前面比较过的,重复比较
            while( j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j = kmpArr[j-1];
            }
            //匹配成功就继续
            if(str1.charAt(i) == str2.charAt(j)) {
                j++;
            }
            //和上面建立kmp数组一样,获得j,匹配成功的长度
            if(j == str2.length()) {//如果相等,匹配完全成功
                return i - j + 1;//返回子串起始下标
            }
            //否则,匹配不成功
        }
        return  -1;
    }
数据结构与算法之字符串匹配算法 字符串匹配算法是在一个文本串中寻找一个模式串出现的算法。其基本原理是在文本串中逐个比较模式串的字符,如果匹配则继续比较下一个字符,如果不匹配则将模式串向右移动一位,继续比较。以下是一些常用的字符串匹配算法:暴力匹配法(Brute Force):从文本串的第一个字符开始,逐个比较模式串和文本串中的字符,如果不匹配则将模式串向右移动一位,继续比较。KMP算法(Knuth-Morris-Pratt):利用模式串本身的特点,在匹配失败时不回溯文本串,而是回溯模式串,让其尽量多地向右移动一位,以提高匹配效率。 阅读详情

相关推荐

KMP算法:数据结构王道考研C++/Java实现指南

数据结构是计算机存储、组织数据的方式,它决定了数据处理的效率。本章将介绍数据结构的一些基础概念,并为理解后续章节中的KMP算法打下基础。数据结构可以定义为数据元素的集合以及它们之间的关系和定义在这些关系上的操作的集合。它主要分为两大类:线性结构和非线性结构。线性结构包括数组、链表、栈、队列等,它们的共同特点是元素之间存在一对一的关系。非线性结构包括树、图等,元素之间存在一对多的关系。时间复杂度是衡量算法效率的一个重要指标,它描述了算法执行时间随输入数据规模增长的变化趋势。

weixin_34471637的博客 1068

Java【KMP算法】大白话式详细图文解析(附代码)

KMP算法(详细且白话)版图文解析,即便你是小白,耐心看完你一定能学会!结尾附源码噢

yzhcjl_的博客 9112

手把手教你为STM32设备生成自定义MAC地址(基于芯片ID的5种算法对比)

本文详细介绍了基于STM32芯片ID生成自定义MAC地址的5种算法,包括直接截取、异或折叠、CRC32哈希、自定义混合运算及SHA-256摘要。通过对比分析各算法的计算复杂度、唯一性及适用场景,帮助嵌入式开发者根据项目规模与资源,选择最合适的方案,确保设备MAC地址的唯一性与合规性。

weixin_29170327的博客 528

【数据结构】KMP算法的详解以及使用JAVA来实现

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。

Superkom666的博客 3118

Ubuntu20.04 高效安装企业微信的完整指南

本文提供了在Ubuntu20.04系统上高效安装企业微信的完整指南,详细介绍了通过Deepin-wine环境运行Windows版企业微信的步骤和优化技巧。内容包括系统环境检查、依赖安装、企业微信包的获取与安装、首次运行配置及常见问题解决方案,帮助开发者在Ubuntu系统中流畅使用企业微信进行办公通讯。

weixin_42568801的博客 353

axi ps读写pl_PL读写DDR:Datamover能干什么

最近发现工程项目中一直在用AXI-DMA。这玩意儿搬数据倒是没问题,就是用axi-lite配置起来非常反人类。。。简单的办法其实是用datamover ip核。这个ip核能干嘛呢。准备写个文章解析一下。由于好多feature没用过,所以仅仅看文档可能理解有误,欢迎指出错误。首先扫个盲:MM2S指的是Memory map to stream. 读DDR. S2MM指的是steam to memory...

weixin_35908791的博客 1598

Java实现KMP算法

java实现KMP

qq_38785977的博客 4536

VTK学习(入门级教程,包括安装和使用)~持续更新中

说明:研究QT+VTK有段时间了,准备把学到的东西分享给大家,这篇博客以VS+QT+VTK为主进行展开学习的。

HXX904的博客 4759

Java笔记——KMP算法

KMP算法的笔记

时刻总结 1796

如何用DETR(detection transformer)训练自己的数据集

DETR(detection transformer)简介 DETR是Facebook AI的研究者提出的Transformer的视觉版本,是CNN和transformer的融合,实现了端到端的预测,主要用于目标检测和全景分割。 DETR的Github地址:link

weixin_50233398的博客 3万+

【案例讲解】LVGL关于旋转的配置

在实现项目中,因为横竖屏的关系,需要对其做90度的旋转。配置旋转时发现一些局部刷新控件,旋转后效果不对。异常图标正常图标。

Bigan(安)的博客 4284

Java进阶实战:经典算法与数据结构题目解析(高级篇)

在掌握了Java基础语法和一些简单的数据结构与算法之后,接下来我们将挑战一些更具深度和难度的题目。这些题目不仅能够帮助你巩固知识,还能提升你的编程思维和解决问题的能力。本文将通过一些经典的高级题目,带你深入理解算法和数据结构的精髓。通过以上几个高级题目,我们深入探讨了动态规划、图算法、字符串匹配和二叉树层次遍历等重要知识点。这些题目不仅能够帮助你巩固基础知识,还能提升你的编程能力和算法思维。希望这些内容对你有所帮助,如果你有任何问题,欢迎在评论区留言讨论。

xuanxuan1235的博客 1087

2026基金本子新规必看!聚焦四大底层问题,利用AI辅助分别破解提升中标率

我拟申报的研究主题为【明确的研究主题或关键词组合】。选题方向也是评审专家关注的核心之一,申报前可以检索近五年领域前人中标项目,分析现有研究的空白与不足,并结合自身研究基础选择 “人无我有、人有我优” 的细分方向,如果是交叉学科选题,则要阐述不同学科的融合逻辑与创新点。“推动国家战略”、“带来行业发展”等宏观表述,有很多同仁都喜欢用这类话术开篇,但实际上宏大叙事无法替代具体的真实科学问题,明确不了研究要解决的核心痛点,更没有说明问题的现实针对性,评审看了往往抓不到研究的核心价值。

智能AI让学术科研更容易 295

Java常见算法与数据结构总结

算法平均时间复杂度最坏时间复杂度空间复杂度特点冒泡排序O(n²)O(n²)O(1)简单易懂,效率低选择排序O(n²)O(n²)O(1)交换次数少插入排序O(n²)O(n²)O(1)适合小规模数据快速排序O(nlogn)O(n²)O(logn)效率高,常用归并排序O(nlogn)O(nlogn)O(n)稳定排序算法核心思想典型应用冒泡排序相邻交换基础排序选择排序寻找最小值基础排序插入排序逐步插入小规模数据快速排序分治。

Moxiaoyong14_cc的博客 660

手把手教你学pcie--内存管理和保护机制(一):MPU与其他内存管理和保护机制详解

MPU(Memory Protection Unit)是一种专门用于 ​。,这些机制通常协同工作,形成多层防御体系,兼顾安全性、性能和灵活性。

MHD0815的博客 279

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

南京工程学院数据结构复习考纲

南京工程学院数据结构复习考纲

ngczx的博客 275

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

数据结构和算法的关系,几个 经典面试题与经典问题

数据结构和算法的关系 数据(data)结构(structure)是一门研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构可以编写出更加漂亮,更加有效率的代码。 要学习好数据结构就要多多考虑如何将生活中遇到的问题,用程序去实现解决. 程序 = 数据结构 + 算法 数据结构是算法的基础, 换言之,想要学好算法,需要把数据结构学到位。 几个经典的面试题 字符串匹配问题 有一个字符串 str1= ““liliwfdxhqwertyuio””,和一个子串 str2=“qwe

一颗西柚的博客 203

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

LeetLode 第八天 28. 实现 strStr() (附KMP算法讲解链接)

LeetCode百日筑基系列主要是为了练习基础的数据结构与算法,题库全为LeetCode简单题(后面会在其他系列更新中等题和困难题),主要使用C语言和Java编写,前期的题目以完成功能为目的,后续会使用更优的算法以及优化代码块。 28. 实现 strStr() 实现 strStr() 函数。 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。 说明: 当 needle 是空字符

Rpk712的博客 230

KMP算法详解

kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法。不过由于其难以理解,所以在很长的一段时间内一直没有搞懂。虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚。在此,综合网上比较好的几个博客(参见最后),尽自己的努力争取将kmp算法思想和实现讲清楚。 kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置。常规方法是遍历

姚光超的专栏 26万+

KMP算法Java实现

package com.dxinl.kmp; import java.util.Scanner; public class KMP { public static void main(String[] args) { new KMP(); } public KMP() { Scanner scanner = new Scanner(System.in); System.ou

For Dream 447

字符串匹配——KMP算法

KMP算法使用JAVA语言实现。 package BFKMPBM; public class BFMatching { public static void main(String[] args) { long startTime; long endTime; long durationTime; startTime = System.nanoTime(); KM

yxdayd的专栏 725

KMP算法代码(java版)

JAVA代码如下: public class KMP { public static void main(String[] args) { KMP kmp = new KMP(); String target="asfsdfssaaabcadsdfaaaaaaaadsf"; String mode="fsdfss"; boolean result=kmp.mathStrin

KeepThinking_的专栏 1439

数据结构与算法 - 字符串匹配优化:KMP算法的next数组原理

字符串匹配(String Matching)是指在一个文本串(Text)中查找一个模式串(Pattern)的过程。具体来说,就是给定一个文本串T和一个模式串P,找出P在T中出现的所有位置。文本串,模式串匹配结果:模式串P在文本串T中的第 0 个位置开始匹配成功,即。KMP算法由Donald Knuth、James Morris 和 Vaughan Pratt 三人于1977年提出,因此得名。它解决了暴力匹配中“回溯”带来的低效问题,通过预处理模式串,构建一个辅助数组(即next。

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

【数据结构与算法】KMP算法

KMP算法

南瓜籽_的博客 910

【Java 数据结构 & 算法】宁可累死自己, 也要卷死别人 17 KMP 算法

【Java 数据结构 & 算法】⚠️宁可累死自己, 也要卷死别人 17⚠️ KMP 算法.

我是小白呀的博客 2052

大话数据结构十一:字符串的模式匹配(KMP算法)

1. KMP算法简介: kmp算法是一种改进的字符串匹配算法,相比朴素算法,KMP算法预先计算出了一个哈希表,用来指导在匹配过程中匹配失败后尝试下次匹配的起始位置,以此避免重复的读入和匹配过程。这个哈希表被称为"部分匹配值表"(Particial match table),这种设计是KMP算法最精妙之处。 2. KMP算法分析: 下面以阮一峰老师博客中的一

技术人生 4352
上一篇: java数据结构与算法刷题-----LeetCode151. 反转字符串中的单词
下一篇: java数据结构与算法刷题-----LeetCode459. 重复的子字符串
ydenergy_殷志鹏
博客等级 码龄7年 5886粉丝 543原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

ydenergy_殷志鹏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值