算法学习——KMP字符串匹配算法

KMP算法是一种非常高效和常用的算法。其核心就是通过预处理一个寻找公共最大前后缀的 Next[ ] 数组,减少匹配失败时的重复无效匹配。

next数组本质:next[ i ] = j 表示下标以 i - j 为起点,i为终点的后缀和下标以0为起点,j为终点的前缀相等。

复制一些别人的图片用来帮助理解next是什么。

然后是kmp算法的思想原理:

下图是主串为:ababaeaba 字串为:ababacd 的一个例子;

例题:

代码:

#include<iostream>
using namespace std;

const int N = 1000010;
//a[]是主串,b[]是模式串,在a[]中寻找b[]
char a[N],b[N];
//ne[]是next数组,由于c++中存在next关键字,所以我们为了避免编译错误,起名ne[]
int ne[N];
//n是主串长度,n是子串(模式串)长度
int n,m;
//预处理ne数组
void prekmp(){
     //模板串长度为1时无前后缀,所以循环从2开始
     for(int i = 2,j = 0;i <= m ;i++){
         //如果刚开始开始匹配或者匹配失败,就返回上一层匹配
         while( j && b[i] != b[j+1]) j = ne[j];
         //如果匹配成功
         if(b[i] == b[j+1]) j++;
         //由于本题要输出全部匹配成功后的位置,所以我们匹配成功一个后,仍然需要回退next数组
         ne[i] = j;
     }
}

void kmp(){
     //开始kmp
     for(int i = 1,j = 0; i <= n; i++){
         while(j && a[i]!=b[j+1]) j = ne[j];
         if(a[i] == b[j+1]) j++;
         //匹配成功,输出起始下标,也就是匹配成功的终点i-模式串长度m=匹配成功的起点
         if(j == m){
           printf("%d ", i - m);
           j = ne[j];
         }
     }
}

int main(){
    //读入模式串
    //下面那行是用c++读入的方式
    //cin>>m>>b+1>>n>>a+1;
    //b[1]和a[1]是为了保证数据读入进来时下标从1开始存放
    scanf("%d%s%d%s", &m,&b[1],&n,&a[1]);
    prekmp();
    //kmp
    kmp();
    return 0;
}     

原文地址:https://www.cnblogs.com/Flydoggie/p/12259502.html

时间: 2024-07-31 16:21:13

算法学习——KMP字符串匹配算法的相关文章

【算法】KMP字符串匹配算法

[原理] (1)next数组原理 (2)特殊情况的处理(巧妙增设哨兵) (3)递推法构造next[]表 [实现代码] #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 100; char t[maxn]; //text char p[maxn]; int next[maxn]; void getNext(){ int m = strlen

KMP字符串匹配算法及next前缀数组的应用

#KMP字符串匹配算法及next前缀数组的应用------ KMP算法通常是我们学习字符串匹配算法时遇见的第一个算法,另外还有Rabin-Karp, Sunday算法等. 相对于其他字符串匹配算法, kmp在字符串中字符重复率低的情况下并不具备优势,那为什么KMP算法会作为经典的教学算法呢? 原因可能是:KMP算法充分利用next前缀数组的信息来优化算法,减小时间复杂度的思路在很多字符串相关问题中能给我们启发. 首先上KMP字符串匹配算法, [leetcode在线测试地址](https://le

KMP字符串匹配算法——用最容易理解的方式描述

看了数据结构书上对于快速模式匹配算法KMP的介绍,感觉云里雾里.本文根据自己理解,并查资料整理了一种非常清晰简单的字符串匹配算法,并给予实现,自诩原创吧. 字符串匹配是我们经常要用到的一种算法,与普通的匹配算法相比KMP算法效率更高,时间复杂度为O(m+n).下面给予详细讲解: 概念详解 设原字符串为"BBC ABCDAB ABCDABCDABDE",待匹配字符串为"ABCDABD". 首先,字符串"BBC ABCDAB ABCDABCDABDE"

KMP字符串匹配算法翔解?

那么首先我们知道,kmp算法是一种字符串匹配算法,那么我们来看一个例子. 比方说,现在我有两段像这样子的字符串: 分别是T和P,很明显,P比T的长度要短很多,我们要做的事情呢,就是找找T中有没有和P相同的一段. 如果按照最简单的办法来做匹配的话,我们一般是一个一个字母的来做. 像这样: 很显然,图中前面3位都是能匹配的,而第四位却不能匹配,怎么办? 这样: 我们就会将整个P字符串向右移动一格,又重新开始,从T中b处与P中第一个a处开始匹配. 如此往复,显然这样是很慢的,因为我们来考虑考虑这样一种

算法学习-KMP(字符串匹配)解释

KMP算法 BF算法 BF算法就是我们最基本的求解字符串匹配的算法,算法的时间复杂度为O(M*N),空间复杂度为O(1),具体过程如下: 串 第一次 第二次 第三次 第四次 模式串S[i] abcababc abcababc abcababc abcababc 匹配串T[j] ababc ababc ababc ababc 可以看到在第三次匹配失败的时候,我们要回溯,直接S串直接i+=1,然后T串j=0从头继续开始.这样复杂度就比较高了. KMP算法 而KMP算法就是为了解决BF算法的复杂度比

KMP字符串匹配算法详解

KMP算法利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息.时间复杂度O(m+n). Next()函数的详解 把将要进行next计算的字符串S分成 k ,j 前后两串,k代表前串开头所在的序号,j代表后串开头所在的序号,起始的时候j=1,k=0. 我们比较一下前串 后串是否相等,要怎么比较呢,肯定是比较S[j]==S[k],如果相等,那么next[j+1]=k+1,然后j++,k++.关键就是理解这

算法导论——朴素字符串匹配算法

package org.loda.string; import org.junit.Assert; /** * * @ClassName: NaiveStringMatcher * @Description: 朴素字符串查找 * * text:abcabaabcabac * pattern:abaa * * @author minjun * @date 2015年7月7日 下午4:02:14 * */ public class NaiveStringMatcher { public static

KMP字符串匹配算法

1 #include<iostream> 2 #include<string> 3 #include<vector> 4 using namespace std; 5 bool matched(string s,int k,int i) 6 { 7 bool result=true; 8 int p=0; 9 int q=i; 10 while(p<k) 11 { 12 if(s[p]==s[q]) 13 { 14 p++;q--; 15 } 16 else 17

28. Implement strStr()(KMP字符串匹配算法)

Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Example 1: Input: haystack = "hello", needle = "ll" Output: 2 Example 2: Input: haystack = "aaaaa",