KMP算法

   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 910
pattern[j]abcabcacab
next[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;
		}
		else
			k = 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++;
		}
		else
			j = 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;
}



 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值