TMD ,KMP!

2023-11-29 18:58
文章标签 kmp tmd

本文主要是介绍TMD ,KMP!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以为搞清楚了BM算法的思想,就容易理解KMP了,shit!还是很难理解关于KMP算法中next数组是如何高效获得的,既然如此暂时不追究了,不过已然不妨碍把代码搞清楚!
跟BM算法类似,KMP算法中主串和模式串的比对也有类似的东西如:坏字符和好前缀。
没错,就是好前缀,BM算法中是好后缀,KMP算法中是好前缀!
在这里插入图片描述
当遇到坏字符的时候,模式串依然是需要往后移动,对于KMP算法来说依然是设法一次滑动多个位置,而不是一个字符一个字符去地低效地比较。
其实就是在好前缀本身的后缀子串中,查找最长的能跟好前缀的前缀子串匹配的串。
在这里插入图片描述
把好前缀的所有后缀子串中,最长的可匹配前缀子串的那个后缀子串叫做最长可匹配后缀子串;对应的前缀子串叫做最长可匹配前缀子串
在这里插入图片描述
如何求解好前缀的最长可匹配前缀子串和后缀子串?这个问题其实只跟模式串本身有关系,既然是好前缀,那么模式串中也一定包含好前缀,那么问题就转化为:求模式串好前缀的最长可匹配前缀子串。
在KMP算法中可以事先根据模式串本身来构建一个存储最长可匹配前缀子串的数组,这个数组的下标为模式串前缀结尾字符的下标(也就是好前缀的候选字符串),值为这个前缀的最长可匹配前缀子串的结尾字符下标。如:
在这里插入图片描述
这个next数组我们称之为“失效函数”,失效函数如何计算出来,一个简单的方法是:如图想求出前缀b[0,4]即ababa这个前缀的最长可匹配前缀的结尾字符下标,可以把b[0,4]的后缀子串全部列举出来跟b[0,4]的前缀去匹配,这样就可以得到最长的可匹配前缀的结尾字符,如图就是ababa的最长前缀子串是aba,结尾字符下标就是2,于是next[4]=2.
在这里插入图片描述
但是这种方式求next数组的值看起来比较低效,高效的方法有,极客时间争哥的课程第34节里有,可惜我没看懂!感觉变量太多了,我是看得绕进去了,感兴趣可以自己去看下,争哥的教程很棒!
下边我就假设next数组已经是被填充的,直接把代码拿上来看看:

package com.study.algorithm;/*** KMP算法* @author jeffSheng* @date 20191001**/
public class Kmp {public static void main(String[] args) {String a = "ababaeabac"+"ababacd"+"xxxx";String b = "ababacd";int x = kmp(a.toCharArray(),a.length(),b.toCharArray(),b.length());System.out.println(x);}// a, b 分别是主串和模式串;n, m 分别是主串和模式串的长度。public static int kmp(char[] a, int n, char[] b, int m) {int[] next = getNexts(b, m);int j = 0;for (int i = 0; i < n; ++i) {while (j > 0 && a[i] != b[j]) { // 一直找到 a[i] 和 b[j]j = next[j - 1] + 1;}if (a[i] == b[j]) {++j;}if (j == m) { // 找到匹配模式串的了return i - m + 1;}}return -1;}// b 表示模式串,m 表示模式串的长度private static int[] getNexts(char[] b, int m) {int[] next = new int[m];next[0] = -1;int k = -1;for (int i = 1; i < m; ++i) {while (k != -1 && b[k + 1] != b[i]) {k = next[k];}if (b[k + 1] == b[i]) {++k;}next[i] = k;}return next;}}

代码我试过了,正常得出结果,对于kmp这个方法可以做如下图解:
在这里插入图片描述
虽然没有搞清楚next数组的高效计算方式,但是理解了整体的思想,我觉得也是够了,能够在实际软件开发中用得上也就可以了,我不觉得非要把那些细节搞清楚!TMD!KMP!

这篇关于TMD ,KMP!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/433945

相关文章

codeforces535D:Tavas and Malekas(KMP)

(i-1 , i)有重合的时候 ,从第i位开始的子串必须是模式串的前缀。 而同时,从第i位开始的子串本来就已经是模式串的后缀了。 typedef long long LL ;const int maxn = 1000008 ;int next[maxn] ;void getnext(char s[]){int len = strlen(s) ;next[0] = -1 ;i

fzu 2275 Game KMP

Problem 2275 Game Time Limit: 1000 mSec    Memory Limit : 262144 KB  Problem Description Alice and Bob is playing a game. Each of them has a number. Alice’s number is A, and Bob’s number i

KMP 详解

KMP数组存的是什么 对于一个字符串 b,下标从1开始。 则kmp[i]表示 以i结尾的连续子串 = s的前缀的最大值(等价于前缀最大结尾处) 如何求KMP 假设 i 以前的KMP都被求出来了。 j 表示上一个字符可以成功匹配的长度(等价于下标) 如果b[j+1] != b[i]下一个位置匹配不上(即不能成为前缀) 则,让j = kmp[j] 即成为以j结尾的 连续子串 的 最长前缀

KMP算法详解 --- 彻头彻尾理解KMP算法

前言     之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k。   但是问题在于如何求出这个最大前后缀长度呢?   我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破,   后来翻看算法导论32章 字符串匹配,虽然讲到了对前后缀计算的正确性,但是大量的推理证明不大好理解,没有与程序结合起来讲。   今天我在这里讲一讲我的一些理解,希望大家多多指教

扩展KMP --- HDU 3613 Best Reward

Best Reward Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613   Mean:  给你一个字符串,每个字符都有一个权值(可能为负),你需要将这个字符串分成两个子串,使得这两个子串的价值之和最大。一个子串价值的计算方法:如果这个子串是回文串,那么价值就是这个子串所有字符权值之和;否则价值为0。

数据结构串的实现以及KMP改进算法

</pre><pre name="code" class="cpp">#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 40 /* 存储空间初始分配量 */typedef int Status; /* Status是

字符串匹配算法之KMP算法和BM算法

[尊重原创]-原文链接在这里->http://blogread.cn/it/article/3975?f=wb 本文主要介绍KMP算法和BM算法,它们分别是前缀匹配和后缀匹配的经典算法。所谓前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从左到右;所谓后缀匹配是指:模式串和母串的的比较从右到左,模式串的移动从左到右。看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同。下文分别

KMP算法 KMP模式匹配 二(串)

B - KMP模式匹配 二(串) Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Description 输入一个主串和一个子串,用KMP进行匹配,问进行几趟匹配才成功,若没成功,则输出0

HDU 1358(kmp)

题意:给出一个数字n,接下来一行是一个字符串,n是这个字符串的长度。求这个字符串的所有是循环字符串的前缀。 kmp中的next数组只得是第i个字符匹配错误,向前跳的位置next【i】。   #include<algorithm>#include<stdio.h>#include<string>#include<string.h>#include<math.h>#include<qu

【HDU2087】【KMP】

剪花布条 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11677    Accepted Submission(s): 7509 Problem Description 一块花布条,里面有些图案,另有一块