KMP算法

来源:互联网 发布:壹方凌网络是干嘛的 编辑:程序博客网 时间:2024/06/18 14:55

   KMP算法是实现单模式匹配的一种算法,而AC算法是实现多模式匹配的算法,两者的区别主要就是多模式和单模式的问题。

一.KMP算法

      KMP算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,其对于任何模式和目标序列,都可以在线性时间内完成匹配查找,而不会发生退化,是一个非常优秀的模式匹配算法。其实KMP算法与BF算法(简单的模式匹配,每次失败都从头再来)的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。

  对于next[]数组的定义如下:编号从1开始

 1) next[j] = 0:j = 1时

 2) next[j] = max(k): 1<k<j P[1...k]=P[j-k+1,j-1]

 3) next[j] = 0 其他

如下:

以模式字符串abcabcacab为例


j 1 2 3 4 5 6 78 910pattern[j]abcabcacabnext[j]0110110501

手工求解Next数组的方法如下:

(1)next[1] = 0;next[2] = 1;(next[0]不使用)

(2)后面求解每一位next[j]的值时,根据j的前一位的next[j-1]求解,令k = next[j-1];

(3)比较S[j-1]与S[k]

a.若相等,next[j] = k+1;

b.若不等,令k=next[k],若K != 0,回到(3),直到next[k] = 0;next[j] = 1.


代码实现:

void get_next(char* T,int next[]){     k = -1;     next[1] = -1;     j = 0;     while(j < (strlen(T)-1))//T[0]存储字符串的长度     {            if(k == -1 || T[k] == T[j])            {                   ++k;++j;next[j] = k;             }             else                    k = next[k];      }}


因此KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则主串(S)的指针i不变,将模式串(T)的指针j移动到next[j]的位置继续进行匹配;若next[j]=0,则将i,j均右移一位(其实此时模式串在第一位),继续进行比较。


代码实现如下:

int KMP(char* s,char* p){int i = 0;int j = 0,int next[100];while(i < strlen(s)){if(j == -1 || S[i] == T[j]){i++;j++;}else    j = next[j];} } 

测试代码

// KMP.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <iostream>#include <string.h>using namespace std;void GetNext(char* p,int* next){int j = 0;int k = -1;next[0] = -1;while (j < (strlen(p)-1)){if (k == -1 || p[j] == p[k]){k++;j++;next[j] = k;}elsek = next[k];}}int KMP(char* s,char* p){int len1 = strlen(s);int len2 = strlen(p);int i = 0;int j = 0;int next[100];GetNext(p, next);while (i < len1){if (s[i] == p[j] || j == -1){i++;j++;}elsej = next[j];if (j == len2)return i - len2;}return -1;}int main(){char s[100] = "abcabaaabaabcac";char p[100] = "abaabcac";int result = KMP(s, p);cout << result << endl;    return 0;}


 


0 0
原创粉丝点击