Implement strStr() 之前在 Leetcode 上 AC 的 O(MN) 版本:Q28 Implement strStr() 解题思路: KMP 算法是经典的求解子串(模式串)出现在主串中位置的算法 KMP 算法的关键:求出子串(模式串)的 next 数组。 Python 实现: class Solution: # KMP 算法 def strStr(self, haystack, needle): """ :
算是一个比较简单的算法吧,主要思想就是空间换时间。挺早之前在知乎上看到一篇文章写的不错,看懂了个大概,但是还没写过。于是趁有时间(偷懒)写了个简单的例子,备忘。 https://www.zhihu.com/question/21923021/answer/1032665486 算法图示 预处理模式串,计算失配后的会退位置 code #include<cstdio next: "); for(int i=0;i<len;i++) printf("%d ",next[i]); puts("\n-----------"); } void KMP int M=strlen(pat); printf("txt_len:%d pat_len:%d\n",N,M); for(int i=0,j=0;i<N;i++){ //在这个算法中 puts("txt:"); scanf("%s",txt); puts("pat:"); scanf("%s",pat); Getnext(pat); KMP
个人网站、项目部署、开发环境、游戏服务器、图床、渲染训练等免费搭建教程,多款云服务器20元起。
KMP为的是解决2字符串匹配问题的算法,检查一个字符串是否为另一个的子串,sub = "abc" , str = "aabcd" ,str里包含了一个sub,KMP算法可以以O(M+N)的复杂度找到子串在 那代码怎么实现呢: public class Kmp { public static void main(String[] args) { String str = "abbabbbbcab char[] s=str.toCharArray(); char[] t=sub.toCharArray(); System.out.println("s包含t的位置"+KMP_Index /** * @param s * @param t * @return 匹配成功 返回模式串在主串中的头下标,匹配失败返回-1 */ public static int KMP_Index
一、KMP算法 image.png public static int[] getNext(char[] chars){ if (chars.length == 1){
在字串匹配领域,有个叫KMP的神算法非常牛x,但是网站和书本的作者介绍这个算法的时候,都会患上临时装逼症,数学推导和概念满天飞,唯恐听者觉浅。 KMP算法的核心意思就是:当我们发现一次比较下来字串没有完全匹配的情况下,下一次的比较也许可以不止往前拱一步,也许可以拱N步,关键是,究竟可以拱几步呢? 个字符匹配,此时N=3,查表得知ABA的部分匹配值x=1,因此我们此时可以往前拱 (3-1)步,接下来比较: ABABBABAABBA ABAAB→ 你发现,此时我们就跳过了一些比较循环,让我们整个算法的效率得到极大的提升 其实KMP算法的核心,就是充分利用比较过的未能匹配的字串的信息,而不是一股脑将他们丢弃。 看到这里的都是有理想的真爱!祝你们洪福齐天!顺便点个分享散播技术正能量鼓励鼓励呗~
$j$表示指向$P$的下标),由于失配,按照暴力做法,下一步的比较是下面这样的: S: ABCDABCDABDE P: ABCDABD 此时$i=1$,$j=0$重新开始比较 KMP next[j]$表示字符串$P$的长度是$j$的前缀的前缀和后缀相等的最大长度 P:ABCDABD next:-1 0 0 0 0 1 2 0 如何求解next数组: 求解$next$数组的代码 void kmp_pre -1] = P[next[n]…n-1]$ 相关题目练习: 1.POJ3461 题目描述: 给$t$组数据,每一组数据给两个字符串$W$和$T$,求字符串$W$在字符串$T$的出现次数 题解: 直接上kmp 有两个序列一个是长度为$n$的数字序列$a$,一个是长度是$m$的数字序列$b$,求最小的$k$使得$a[k…k+m-1] = b[1…m]$ 题解: 就是求$b$在$a$中第一次出现的位置,直接上kmp kmp的$next$数组简直就是米奇妙妙屋 #include <bits/stdc++.h> using namespace std; typedef long long LL; #define dbg
Kmp算法是一种效率极高的串匹配算法,适用这样的场景,在给定文本串text中查找是否含有指定的模式串pattern。 效率高的原因:利用部分匹配的信息,将已经匹配到信息存入next数组。 类似的有求最大回文串长度的manacher算法。 时间复杂度O(n+m) 最长公共前后缀 next数组的求解 next数组可以称之为prefix table,前缀表。 =s[j+1]) j = Next[j]; if (s[i] == s[j+1]) j ++; Next[i] = j; } } bool kmp(char *text, char *pattern
KMP为字符串匹配算法,在朴素匹配算法基础中,每当匹配失败匹配串就要回到开始匹配的地方,这样字符串大的话就会很慢,特别是"abcabcabcd" "abcd"这种。 KMP利用前面匹配失败的串,比如str1 = "abcdeabcdeabp" str2 = "abcdeabp",当在'p'匹配失败时,str2的指针可以回退到'c'的位置,因为c前面是ab,str1
KMP算法 在正式进入KMP算法之前,不得不先引经据典一番,因为直接去理解KMP,你可能会很痛苦(别问,问就是我也痛苦过)。 因此,引出了今天的主角KMP算法。 通过上面的演示,不难得出BF算法的代码。 算法完整代码 搞清楚了next数组的求解,kmp算法也就是信手拈来的事了。 复杂度分析 BF算法 O(mxn) KMP算法 O(m+n) 补上八股文 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特 —莫里斯—普拉特操作(简称KMP算法)。
KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。说简单点就是我们平时常说的关键字搜索。 大牛们是无法忍受“暴力破解”这种低效的手段的,于是他们研究出了KMP算法,其思想就如同我们上边所看到的一样:“利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置 所以,整个KMP的重点就在于当某一个字符与主串不匹配时,我们应该知道j指针要移动到哪? = next[k]; }else { next[j] = k; } }else { k = next[k]; } } } int str_index_kmp pos = str_index(buf, t, 0); if (pos > 0) { printf("%s\n", buf + pos); } pos = str_index_kmp
BF算法性能比较低,特别是在每趟匹配不成功时存在大量回溯,没有利用部分已经匹配成功的结果 KMP算法:与BF算法不同,会舍弃重复比较的过程 BF算法 ? KMP算法伪代码描述 ? ? next数组的求值 #include<iostream> using namespace std; #include<string> //KMP //1.求出T字符串每一个字符对应的next值,然后存放到 [j] = i; } //如果失配 else { //i回溯到当前next值的位置 i = next[i]; } } } //返回子串T在s串中开始位置下标 void KMP KMP算法完整代码 #include<iostream> using namespace std; #include<string> //KMP //1.求出T字符串每一个字符对应的next值,然后存放到
[edit by xingoo] kmp算法其实就是一种改进的字符串匹配算法。复杂度可以达到O(n+m),n是参考字符串长度,m是匹配字符串长度。 传统的算法,就是匹配字符串与参考字符串挨个比较,如果相同就比较下一个,如果不相同,就返回上一次的结果,再重新比较。 匹配代码 int kmp(char* S,char * T){ int i=0; int j=0; int next[MAX]; getNext(T,next); <stdlib.h> 3 #include <string.h> 4 #define MAX 20 5 6 void getNext(char * T,int *next); 7 int kmp j; 32 } 33 else{ 34 j = next[j]; 35 } 36 } 37 } 38 39 int kmp
简介 KMP 算法是一种改进的字符串匹配算法,KMP 算法是由 D.E.Knuth,J.H.Morris 和 V.R.Pratt 三人提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称 KMP 算法 KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 next() 函数实现,函数本身包含了模式串的局部匹配信息。 i - j : -1; } kmp匹配 模式串ABCABD计算出部分匹配表,匹配表如下: 字符 A B C A B D 匹配值 0 0 0 1 2 0 /** * 部分匹配值就是前缀和后缀的最长共有元素的长度 if (match[k] == match[i]) k++; next[i] = k; } return next; } int kmp
我觉得复到KMP应该就够用了,如果要AC自动机我直接死在那里。 参考资料 如何更好地理解和掌握 KMP 算法? - 阮行止的回答 - 知乎 https://www.zhihu.com/question/21923021/answer/1032665486 核心思想 KMP算法要解决的问题是字符串匹配问题。 KMP的想法是充分利用适配信息,其next数组的定义如下:next[i]表示在P[0:i]子串中,使前k个字符恰好等于后k个字符的最大的k,且k不能等于i+1(否则就等于它自己了) 这个数组的定义挺绕的 KMP的失配匹配,本质上就是把模版串向前伸,直到伸到前缀与后缀匹配为止,这实际上就是自己与自己匹配。因此这个k就是前缀与后缀相同的最大长度k。 快速求next数组 这一步也是KMP的精髓,前面我没记错的话应该是MP算法,这一步是K算法。 其核心在于让P自己与自己做匹配。
最近由于某些原因,又回顾了一次KMP算法。 上一次回顾KMP算法还是在刷题的时候遇到的: http://blog.csdn.net/dacc123/article/details/50994611 在我的记忆力,每次回顾KMP算法都会有新的理解, KMP算法其实很简单,就从前缀和后缀去理解他,这也是他算法的核心思想。
else nextval[i] = j; } else j = nextval[j]; } } int kmp 1); scanf("%s", s + 1); memset(nextval, 0, sizeof(nextval)); get_next(t); int pos = kmp
具体参见: KMP算法详解 背景: KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。 其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。 KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将 在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。 0 ; 15 } 16 } 17 18 return next ; 19 } 通过next采用KMP
概述 KMP是字符串匹配的经典算法。其中包含的思想,是非常有趣的。本文作为KMP算法的介绍和备忘录。 场景 KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。 BF算法是一种蛮力算法。 所以,我们只需要将上面的BF算法,稍作修改,就可以优化我们的时间复杂度,优化之后的算法,就是KMP算法。 KMP 先说结论,KMP算法,其实就是将上面的BF算法的。 总结 所以 KMP的理解和记忆,可分为三部分。BF算法、假设有getNext的计算方式和getNext的实现。 其中 getNext中,最复杂的就是k = next[k]这一回跳递归逻辑。 有以上几点,KMP就不那么难了。 如有问题,欢迎指正。
**说明:Sk直接跳到Sk+1,也就是通常所说的简单模式匹配算法中i不需要回溯。** 注意:MP算法中的i不需要回溯这里隐藏着一个考点。 算法较之于简单模式匹配算法的优势时,不要忘掉这一点。 Sk直接跳到Sk+1的改进算法,这就是知名的KMP算法,代码如下: int KMP(Str str,Str substr,int next[]) { int i = 1,j = 1;//串从数组下标1 算法的改进 先看一种特殊情况,见表7。 算法改进的切入点。
腾讯云神图·人脸融合通过快速精准地定位人脸关键点,将用户上传的照片与特定形象进行面部层面融合,使生成的图片同时具备用户与特定形象的外貌特征,支持单脸、多脸、选脸融合,满足不同的营销活动需求……
扫码关注腾讯云开发者
领取腾讯云代金券