精华内容
下载资源
问答
  • KMP算法代码

    2016-09-12 16:14:11
    KMP next算法
  • kmp算法代码

    2013-01-01 11:54:26
    kmp算法 可以参考的C代码 包含了具体kmp算法的核心代码
  • KMP算法代码详解

    千次阅读 2020-09-03 02:00:57
    学习了kmp算法,思想其实很好理解,但是代码的实现一直看得很迷糊。看了很多博客,特别是对匹配信息的next数组有很多不同,比如数组有首位有-1的也有0的等。我自己也疏离了一遍,记录一下,方便之后以后回忆。 首先...

    在这里插入图片描述
    学习了kmp算法,思想其实很好理解,但是代码的实现一直看得很迷糊。看了很多博客,特别是对匹配信息的next数组有很多不同,比如数组有首位有-1的也有0的等。我自己也疏离了一遍,记录一下,方便之后以后回忆。
    首先KMP算法主要是用来解决字符串(也叫主串)中的模式串定位问题,比如,有一个主串"abaabaabbabaaabaabbabaab",要找出主串中是否存在子串"abaabbabaab",并返回匹配到的具体位置。
    在这里插入图片描述

    如果是普通的暴力匹配,应该是将主串和模式串从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位。比如
    在这里插入图片描述
    在匹配到第4位的时候,发现与模式位不匹配,则将模式串向右移动一位继续从头开始匹配。
    在这里插入图片描述
    再发现注册的第2位字符和模式串的第1位字符不匹配,模式串继续右移
    在这里插入图片描述
    然后再依次匹配,最终算出结果。这种方式的时间复杂度较高为O(m*n)。
    其实观察上面的匹配过程,在第一次主串第4位和模式串第4位匹配不成功的时候,因为前三位其实已经匹配过了。并且模式串第2.3位没有与第1位a匹配的。也就是说,在暴力匹配中的第二次向右平移用主串的第二位b与模式串第一位a,第三次向右平移,用主串的第三位c与模式串第一位a做匹配,是必然失败的。所以可以省略这样的步骤。将模式串第一位a直接与主串刚刚匹配失败的第四位a做匹配。
    在这里插入图片描述
    在一一匹配后,发现主串的第10位与模式串的第7位不匹配,此时,之前与模式串匹配过的前6位中 abcdab,后缀ab与模式串开头ab是相同的,无须比较,可以将模式串的第三位移到主串不匹配的第10位底下进行比较。
    在这里插入图片描述
    KMP算法其实就是主串不去移回已经比较过的位置内容,利用已经匹配过的已知信息,在模式串中筛选出合理的位置字符,去与主串的字符做匹配,这样就提高了效率。这一步的时间复杂度就只有O(m)了。但是在匹配失败后怎么知道主串的这个字符要与模式串的哪个字符做匹配呢?这里就需要一张匹配表,一般都喜欢用next数组来表示。索引从0开始,一一对应模式串的字符。对应索引的数组值是匹配失败后,模式串下一个与主串对应字符匹配的字符索引(也可以理解为最长前后缀匹配的位数)。所以求next数组需要遍历模式串,时间复杂度为O(n),总体整个KMP算法的时间复杂度为O(m+n)。

    这里说下怎么求next数组吧,具体的理论可以去参考其他的博客,这里就不再详细的介绍了,主要是来记录了解代码的。

    首先在已匹配模式串中,如果以i代表模式串的索引,j代表匹配重复子串(最大前后缀)的索引+1。从开头到结束不包括模式串结尾属于前缀,从结尾到开头(不包括开头)叫后缀。比如模式串abcdabd,如果已经匹配了6位,最后第7位d匹配失败,d所对应的前缀都有 a、ab、abc、abcd、abcda,所对应的后缀有b、ab、dab、cdab、bcdab,他们的相同前缀为ab。已经匹配过的字符中,第3位c与匹配失败的第7位d有相同的前缀ab,并且ab是模式串的开头,所以在下一次匹配中,可以跳过ab,直接将第3位c移动到现在匹配失败d的位置。也就是主串对应的字符在匹配d失败后直接就与第3位c做匹配。那么next[6]的值就是c的索引2,也等于最大子串匹配的长度。

    因为模式串开头第一个字符是没有前缀的,所以可以设置一个特殊的数字next[0]=-1,从第二个字符开始做匹配,i=1。j=0,因为比较重复子串都是从开头也就是模式串第一个字符做比较的。如果i字符与要比较的j字符相同,那么i、j分别加1,这个位置next[]数组就是对应j的值,所以如果最大重复子串长度为1则j在索引1的位置代表索引0位置的字符已经匹配。如果j位置匹配失败,则j回溯到next[j]位置继续匹配,next[]数组的值本来就是对应位置匹配失败后,应该去匹配的索引位置,前面已经介绍过了。

    如果j在索引0的位置还是匹配失败了,就说明对应失败位置前面没有任何重复的子串,那么匹配的模式串不需要再匹配,值为0,再将i索引加1进行下个字符的匹配。而next[0]的值为-1,所以j的值也应该加1,重置为索引0,继续从开头做匹配。

    所以大概的求next数组的代码是

    public static int[] getNext(String s) {
            char[] chars = s.toCharArray();
            int i = 0;
            int j = -1;
            int[] next = new int[s.length()];
            next[0] = -1;
            while (i < next.length - 1) {
                if (j == -1 || chars[i] == chars[j]) {
                        next[++i] = ++j;
                } else {
                    j = next[j];
                }
            }
            return next;
        }
    

    有了next数组后,在主串与模式串不匹配的时候,就知道需要换模式串的哪个索引字符去和主串匹配了。

        public static int kmp(String s, String t) {
            int[] next = getNext(t);
            //主串位置
            int i = 0;
            //模式串位置
            int j = 0;
            while (i < s.length() && j < t.length()) {
                if (j == -1 || s.charAt(i) == t.charAt(j)) {
                    i++;
                    j++;
                } else {
                    j = next[j];
                }
            }
            if (j == t.length()) {
                return i - j;
            } else {
                return -1;
            }
        }
    

    s为主串,t为模式串,j==t.length(),只有在模式串完全匹配的情况下才会发生,不然j的值会不停被回溯为数组的其他索引上,方法会返回模式串与主串匹配的第一个字符索引,如果匹配不到完整的模式串,则返回-1。

    这个kmp算法还有一些缺陷,看下面例子
    在这里插入图片描述
    下面是模式串,第6位b与主串第9位c不匹配,根据kmp算法可以算出第6位也就是next[5]的值是1,但是索引1位置也是个b,与第6位重复了,并且第6位与c已经比较过了,不匹配,所以回溯后,索引1位置b与c肯定也是不匹配的。这一步属于多余操作,最终他会与模式串索引是索引1位置的next数组值的字符做匹配。所以在匹配到相同前后缀后,还需要判断一下是否相同,如果相同则跳过。改进下求next数组的代码

        public static int[] getNext(String s) {
            char[] chars = s.toCharArray();
            int i = 0;
            int j = -1;
            int[] next = new int[s.length()];
            next[0] = -1;
            while (i < next.length - 1) {
                if (j == -1 || chars[i] == chars[j]) {
                    if (chars[++i] == chars[++j]) {
                        chars[i] = chars[j];
                    } else {
                        next[i] = j;
                    }
                } else {
                    j = next[j];
                }
            }
            return next;
        }
    
    展开全文
  • KMP算法代码实现

    万次阅读 2018-04-26 15:00:27
    KMP算法的核心思想是避免匹配失败时重新从短串的第一个字符开始匹配,从而提高匹配效率。#include &lt;iostream&gt; #include&lt;cstdio&gt; #include&lt;cstdlib&gt; #include&lt;...

    KMP算法的核心思想是避免匹配失败时重新从短串的第一个字符开始匹配,从而提高匹配效率。

    #include <iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include <string>
    typedef long long ll;
    using namespace std;
    //未改进的KMP算法代码实现
    void get_next(int *next, char *T, int len)
    {
    	next[0] = -1;//-1代表没有重复子串
    	int k = -1;
    	for (int q = 1; q <= len; q++)
    	{
    		while (k > -1 && T[k+1] != T[q])//下一个元素不相等,把k向前回溯
    		{
    			k = next[k];
    		}
    		if (T[k+1] == T[q])//下一个元素相等,所以最长重复子串+1
    		{
    			k = k+1;
    		}
    		next[q] = k;//给next数组赋值
    	}
    }
    int KMP(char *s, int len, char *p, int plen)//利用KMP算法匹配
    {
    	int *next = new int(plen);
    	get_next(next, p, plen);
    	int k = -1;
    	int i = 0;
    	for (; i < len; i++)
    	{
     		while (k > -1 && p[k+1]!=s[i])//两串下一个字符不相等,向前回溯(效率高就是在这里,每次匹配失败,k不用直接变为0,从第一个字符开始重新匹配,而是变为最长重复子串的下一个字符,从中间开始匹配即可)。
    		{
    			k = next[k];
    		}
    		if(p[k+1] == s[i])//两个串的字符相等,k+1来匹配子串的一个字符
    		{
    			k++;
    		}
    		if (k == plen-1)//匹配成功,返回短串在长串的位置。
    		{
    			return i-plen+1;
    
    		}
    	}
    	return -1;
    }
    int main()
    {
    	
    	char a[] = "bacbababadababacambabacaddababacasdsd";
    	char b[] = "ababaca";
    	int m = KMP(a,strlen(a),b,strlen(b));
    	printf("%d", m);
    	return 0;
    }
    

    展开全文
  • KMP算法代码(C语言)

    千次阅读 2019-04-09 18:53:39
    KMP ( char s1 [ ] , char s2 [ ] ) { int i = 0 ; int j = 0 ; int len1 = strlen ( s1 ) ; int len2 = strlen ( s2 ) ; while ( i < len1 && j < len2 ) { if ( j == - 1 || s1 [ i ...
    int next[1000000];
    void get_next(char s[])
    {
        int i=0;
        int j=-1;
        next[0]=-1;
        int len=strlen(s);
        while(i<len-1)
        {
            if(j==-1||s[i]==s[j])
            {
                i++;
                j++;
    			next[i]=j;
            }
            else
            {
                j=next[j];
            }
        }
    }
    int KMP(char s1[],char s2[])
    {
        int i=0;
        int j=0;
        int len1=strlen(s1);
        int len2=strlen(s2);
        while(i<len1&&j<len2)
        {
            if(j==-1||s1[i]==s2[j])
            {
                i++;
                j++;
            }
            else
            {
                j=next[j];
            }
        }
        if(j>=len2)
            return i-len2+1;
        else
            return -1;
    }
    
    展开全文
  • KMP算法实现的C++代码

    2017-10-24 10:43:13
    KMP算法实现的C++代码KMP算法实现的C++代码KMP算法实现的C++代码
  • 主要介绍了KMP算法的相关知识以及python如何实现,帮助大家更好的进行数据分析,感兴趣的朋友可以了解下
  • KMP算法代码示例,,,
  • 「天勤公开课」KMP算法易懂版_哔哩哔哩_bilibili 帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili 以上两个视频第一个主要是讲解思路,第二个阐述了代码实现以及运行过程,讲解很清晰 代码: /...

    讲解视频推荐:

    「天勤公开课」KMP算法易懂版_哔哩哔哩_bilibili

    帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili

    以上两个视频第一个主要是讲解思路,第二个阐述了代码实现以及运行过程,讲解很清晰

    代码:

    //KMP算法
    #include <bits/stdc++.h>
    using namespace std;
    
    void getnext(int* next,string s){
    	//初始化  处理相等的情况 
    	//不想等的情况 更新数组的值 
    	int i,j=0;//j代表前缀末尾  i代表后缀的末尾
    	next[0]=0;//初始回退到0
    	for(i=1;i<s.size();i++){
    		while(j>0&&s[i]!=s[j])j=next[j-1];//回退 到上一位
    		if(s[i]==s[j])j++;
    		next[i]=j; 
    	}
    	return;
    }
    
    int kmp(string text,string s,int* next){
    	int n=text.size();
    	int m=s.size();
    	getnext(next,s);//预处理next数组
    	int i,q;
    	for(i=0,q=0;i<n;i++){
    		while(q>0&&s[q]!=text[i])q=next[q-1];//匹配不到
    		
    		if(s[q]==text[i])q++;
    		if(q==m){
    			//匹配成功 返回上一位
    			return i-q+1; 
    		} 
    	}
    	//匹配失败返回-1 
    	return -1;
    }
    
    int main(){
    	string text="ABAABAABBABAAABAABBABAAB";
    	string temp="AABBABAAB";
    	int len=temp.size();
    	int arr[len+1];
    	getnext(arr,temp);
    	cout<<kmp(text,temp,arr)<<endl;
    	return 0; 
    }
    
    

    展开全文
  • 本人用的是清华大学严蔚敏教授编写的数据结构教材,利用代码实现kmp算法 /*KMP算法 数据结构书上版代码实现*/ #include <stdio.h> #include <math.h> #include <string.h> int main(void) { ...
  • 串的模式匹配算法之KMP算法代码 KMP算法是一种字符串的模式匹配算法,使用BF(Brute Force,暴力)算法的时间复杂度为O((m - n + 1)*n),使用KMP算法的时间复杂度为O(m + n)。 其中m为主串的长度,n为模式串的...
  • 字符串模式匹配中的KMP算法详解,了解前后缀与真前后缀,代码图文方式详解next数组求解以及模式串如何回溯过程
  • KMP算法源代码 C语言

    2017-04-26 20:46:03
    KMP算法源代码 C语言 KMP算法源代码 C语言 KMP C语言
  • 数据结构 KMP算法代码

    千次阅读 2014-03-28 13:25:50
    //匹配字符串模式值  void getFail(char P[],int f[]) { int m=strlen(P); f[0]=0; f[1]=0; for(int i=1;i { int j=f[i]; while(j&&P[i]!=P[j])  j=f[j]; f[i+1] =P[i]==P[j] ?...//比较匹配算法 
  • 4.3.2 KMP 算法 KMP 算法是 D.E.Knuth J.H.Morris 和 V .R.Pratt 共同提出的 , 简称 KMP 算法算法较 BF 算法有较 大改进 , 主要是消除了主串指针的回溯 , 从而使算法效 率有了某种程度的提高 所谓 真子串 是指模式...
  • KMP算法代码实现中,最重要也是最难理解的,就是next数组,下面直接上图: 首先,先假设我们已知了next数组的next[j]=k,意思就是j位置之前,由k-1个相同前后缀 接下来,在已知的前提下,推导j+1的情况,如果j...
  • #include <stdio.h>...int KMP(char s1[],char s2[],int next[]); int main() { int i= 0; int next[1000]; char s2[] = "abcac"; char s1[] = "ababcabcacbab"; get_next(s2,next); i=KMP(s1,
  • KMP算法(C++实现)

    2013-07-08 11:16:42
    *KMP算法的思想就是在匹配过程称若发生不匹配的情况 *如果next[j]>=0则目标串的指针i不变将模式串的指针j移动到next[j]的位置继续进行匹配 *若next[j]=-1则将i右移1位并将j置0继续进行比较 *...
  • KMP算法c++代码

    千次阅读 2019-04-15 21:26:11
    先放代码,对着代码来讲一讲(代码没加注释) #include<iostream> #include<string.h> const int MAXLEN = 50; int next[MAXLEN] = { 0 }; int nextval[MAXLEN] = { 0 }; void get_next(char s[],...
  • KMP算法--c语言源代码

    2021-05-21 10:25:03
    KMP算法/*** name:KMP* time:2012-11-22* 字符串快速匹配*/#include#includetypedef struct seqstring{char string[100];int length;}seqstring;void getnext(seqstring p,int next[]){int i,j;next[0]=-1;//next[0]...
  • Kmp算法完整代码

    千次阅读 2019-10-25 17:37:58
    kmp ( char s1 [ ] , char s2 [ ] , int next [ ] ) { int lens1 = strlen ( s1 ) ; int lens2 = strlen ( s2 ) ; int i = 0 , j = 0 ; while ( i < lens1 && j < ...
  • 1 KMP算法 KMP算法使用来解决,一个字符串是否为另一个字符串的子的问题,KMP算法之所以高效是 因为匹配失败时,总是能够让模式串回退到某个位置,使文本不用回退。而其重点难点也就是在于模式串到底要回退多少才...
  • KMP算法代码(可运行)

    2021-06-30 09:33:21
    KMP算法 下面的代码是可以运行的,拿回去研究研究吧 #include <iostream> #include <string> using namespace std; #define Max 30 void GetNext(string T, int next[], int length) { next[0] = -1; ...
  • kmp算法c++代码实现(完整版详解)

    千次阅读 多人点赞 2020-02-25 18:23:02
    难理解的还是前后缀表的问题,这个表存的...为什么第一个位置是-1,是因为当他为0的时候在kmp中 当len=0时,(len=prefix[len])之后len=-1,再加1正好是0的下标。 代码 #pragma GCC optimize(3,"Ofast","inline") #...
  • C语言KMP算法的实现

    2021-05-21 10:25:02
    KMP算法在模式与主串之间存在许多“部分匹配”的情况下,比BF算法快。(注意,接下来的串都是以下标为1作为起始储存位置。)下面说一下实现代码:首先是预定义和类型定义:#define MAXLEN 100typedef struct{char ch...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,322
精华内容 10,528
关键字:

kmp算法代码