KMP字符串模式匹配算法(C++实现)

鉴于原理有点复杂,详细原理可以参考这篇文章http://blog.csdn.net/v_july_v/article/details/7041827

  本文直接从结论入手,应付考试和竞赛足够了。

  设T为目标串("aaabbbaabbabcabcabbaba"),pat为模式串("aabbabc")。

  这是模式串的next数组:

j(下标) 0 1 2 3 4 5 6
pat a a b b a b c
next[j] -1 0 1 0 0 1 0

  KMP算法:

  j=0时,next[j]=-1。表示下一趟匹配比较时,模式串的第-1个字符与目标串上次失配的位置对齐。(其实等同于第0个字符与目标串上次失配的下一个位置对齐),模式串需要移动到posT-next[j]的位置。(posT为T串下标)

  j=1时,next[j]=0。表示下一趟匹配比较时,模式串的第0个字符与目标串上次失配的位置对齐。模式串需要移动到posT-next[j]个位置。

  j=2时,next[j]=1。表示下一趟匹配比较时,模式串的第1个字符与目标串上次失配的位置对齐。模式串需要移动到posT-next[j]个位置。

  以此类推......

  

  那么下面只要求出next数组即可,next数组是如何形成的?

  从下标0开始,一直到lengthP-1为止(lengthP是模式串的长度),每次寻找该下标前面前缀与后缀相同的最大长度(前后缀不包括前面整个字符串,即起始位置和终止位置都相等的那一个字符串,下面有解释)。

  j=0时,字符a前面无字符,故标记-1;

  j=1时,字符a前面有字符a,但由于“前后缀不包括前面整个字符串”的规则,所以并没有相同的前后缀一说,故标记为0。

  j=2时,字符b前面有字符aa,前后缀相同的字符串为a,故标记为前后缀的长度1。

  以此类推......(PS:前后缀的计算都是从左到右的)

  其实这样说是为了方便理解next数组,而next数组的实际形成也是一次KMP算法,它也是一个匹配字符串的过程,用后缀去匹配前缀的过程。

  代码如下:

  

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 string T;
 5 string pat;
 6 void getNext(int next[],int lengthP){//lengthP为模式串P的长度
 7     int j=0,k=-1;//j为P串的下标,k用来记录该下标对应的next数组的值
 8     next[0]=-1;//初始化0下标下的next数组值为-1
 9     while(j<lengthP){ //对模式串进行扫描
10         if(k==-1||pat[j]==pat[k]){//串后缀与前缀没有相等的子串或者此时j下标下的字符与k下的字符相等。
11             j++;k++;
12             next[j]=k;//设置next数组j下标的值为k
13         }else
14             k=next[k];//缩小子串的范围继续比较
15     }
16 }
17
18 int kmp(int k,int next[]){
19     int posP=0,posT=k;//posP和posT分别是模式串pat和目标串T的下标,先初始化它们的起始位置
20     int lengthP=pat.length();//lengthP是模式串pat长
21     int lengthT=T.length();//lengthT是目标串T长
22     while(posP<lengthP&&posT<lengthT){//对两串扫描
23         if(posP==-1||pat[posP]==T[posT]){//对应字符匹配
24             posP++;posT++;
25         }else
26             posP=next[posP];//失配时,用next数组值选择下一次匹配的位置
27     }
28     if(posP<lengthP) return -1;
29     else return posT-lengthP;//匹配成功
30 }
31
32 int main(){
33     T="aaabbbaabbabcabcabbaba";
34     pat="aabbabc";
35     int lengthP=pat.length();
36     int next[lengthP]={0};
37     getNext(next,lengthP);
38     int pos=kmp(0,next);
39     cout<<pos<<endl;
40     cout<<"next[]:";
41     for(int i=0;i<lengthP;i++){
42         cout<<next[i]<<" ";
43     }
44     return 0;
45 }

  

  

  

  

  

时间: 2024-10-25 05:40:59

KMP字符串模式匹配算法(C++实现)的相关文章

kmp字符串模式匹配算法

概述 ??kmp算法我觉得有两个关键点:1.计算模式字符串的部分匹配表(这时候,自己跟自己比较)2.匹配主串时候,主串字符只遍历一遍,匹配时候,根据模式串的部分匹配表计算模式串应该移动的位置.kmp算法时间复杂度为O(m+n);下面我实现的算法代码(PHP) 理论 关于kmp理论部分,这篇文章写得好:http://kb.cnblogs.com/page/176818/.我就不再赘述了. 计算部分匹配表 function kmp_next($string){ $length = strlen($s

[转] 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽

字符串模式匹配算法——BM.Horspool.Sunday.KMP.KR.AC算法一网打尽 转载自:http://dsqiu.iteye.com/blog/1700312 本文内容框架: §1 Boyer-Moore算法 §2 Horspool算法 §3 Sunday算法 §4 KMP算算法 §5 KR算法 §6 AC自动机 §7 小结 §1 Boyer-Moore(BM)算法 Boyer-Moore算法原理 Boyer-Moore算法是一种基于后缀匹配的模式串匹配算法,后缀匹配就是模式串从右到

字符串模式匹配算法--详解KMP算法

在软考的复习中,看到过几次  字符串的模式匹配算法.看起来挺难的.所以花了点时间查了查关于字符串匹配的算法.下面详细介绍一下KMP模式匹配算法 什么是字符串的匹配? 在文章中进行查找.需要找到要查找的内容所在的位置.就是字符串的匹配. 朴素的模式匹配算法 朴素的模式匹配算法,就是把要查找的内容,一步步的与要查找的文章进行进行比较.如果匹配失败,则主串和字串回溯.字串位置加1.重新匹配. 模式匹配算法的流程如下: 在匹配失败的情况下,模式串仅右移一个 之后.在从头开始匹配. 两个for循环 For

字符串模式匹配算法之二:KMP算法

KMP算法简介 KMP算法全称叫做Knuth-Morris-Pratt Algorithm. 被搜索的字符串称为主串,待搜索的字符串称为模式串. 我们知道朴素模式匹配算法:http://blog.csdn.net/chfe007/article/details/43448655是很低效的,KMP算法从模式串出发,发现模式串中隐藏的信息来减少比较的次数,具体如何做到的可以移步这个链接:http://kb.cnblogs.com/page/176818/ KMP算法的关键在于next数组值的推导.

Java数据结构之字符串模式匹配算法---Brute-Force算法

模式匹配 在字符串匹配问题中,我们期待察看源串 " S串 " 中是否含有目标串 " 串T " (也叫模式串).其中 串S被称为主串,串T被称为子串. 1.如果在主串中查找到子串,则称为模式匹配成功,返回模式串的第一个字符在主串中出现的位置. 2.如果在主串中未找到子串,则称为模式匹配失败,返回-1. 在模式匹配过程中有两个比较经典的算法:Brute-Force与KMP算法是两种最经典的模式匹配算法. 在本片中主要分析BF算法,很黄很暴力.下面是简单的思路解析:  

字符串模式匹配算法之一:朴素模式匹配算法

被搜索的字符串称为主串,待搜索的字符串称为模式串.朴素模式匹配算法的基本思想: 对主串的每一个字符作为子串开头,与模式串进行匹配.对主串做大循环,每个字符开头做模式串长度的小循环,直到匹配成功或全部遍历完成为止. 代码实现非常简单: int strStr(char *haystack, char *needle) { for (int i = 0; ; ++i) { for (int j = 0; ; ++j) { if (!needle[j]) return i; if (!haystack[

Java数据结构之字符串模式匹配算法---KMP算法

本文主要的思路都是参考http://kb.cnblogs.com/page/176818/ 如有冒犯请告知,多谢. 一.KMP算法 KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,其基本思想是:每当匹配过程中出现字符串比较不等时,不需回溯指针,而是利用已经得到的"部分匹配"结果将模式向右"滑动"尽可能远的一段距离,继续进行比较.显然我们首先需要获取一个"部分匹配"的结果,该结果怎么计算呢? 二.算法分析 在上一篇中讲到了BF算法,

Java数据结构之字符串模式匹配算法---KMP算法2

直接接上篇上代码: 1 //KMP算法 2 public class KMP { 3 4 // 获取next数组的方法,根据给定的字符串求 5 public static int[] getNext(String sub) { 6 7 int j = 1, k = 0; 8 int[] next = new int[sub.length()]; 9 next[0] = -1; // 这个是规定 10 next[1] = 0; // 这个也是规定 11 // 12 while (j < sub.l

字符串模式匹配算法

定义:设有主串S和子串t,子串的定位就是要在主串S中找到一个与子串t相等的子串.通常把主串S称作目标串,子串t称作模式串,因此定位也称作模式匹配. 常用两种算法: 1brute-force算法 思路:主串标记指针每次移动一个位置,然后和子串比较,如何相等则返回当前主串指针的位置. 模式匹配过程如图: 图略 上面算法的缺点:主串指针回溯,当与模式串部分匹配后,每次主指针只移动一个位置. 2.kmp算法 思路:分析模式串,从而避免不必要的回溯.构建模式数组. 过程:模式串t="abcabd"