KMP算法以及 next 数组求解

这几天折腾了下KMP,终于算是理解了其中的原理。现在这里大概记录下,以备不时之需!!

 

  

char str[MAXN];    //原串    
char p[MAXN];    //需要在原串中寻找的字符串

  

 

相对于一般的字符串匹配,KMP算法优化的地方就在于   当发现当前匹配的位置 k + 1 匹配失败时,不是再回到 p 的开始位置进行匹配,而是回到 next[k] 开始匹配!

next[k] 记录了 p[0...k] 中,最长的相同前缀后缀长度 - 1 , -1 是为了转移的时候方便(数组从 0 开始)。

比如:

对于

/*
p:

| a | b | a | a | b | c | a | c |

next:

| -1| -1| 0 | 0 | 1 | -1| 0 | -1|
*/

  

相同前缀后缀就是前缀和后缀相同;

 

然后就是 next 数组的求法:

这里照搬一下算法导论中的代码,很巧妙,如果不知道原理模拟一下就清楚了。

void get_next(char *p, int *next){
    next[0] = -1;
    int k = -1;
    for(int i = 1; i < p.length; i++){
        while(k > -1 && p[k + 1] != p[i])
            k = next[k];
        if(p[k + 1] == p[i]){
            k++;
        }
        next[i] = k;
    }
}

  

有了 next 数组之后,在匹配字符串程序中发现不匹配的位置时,不需要将 p 的位置变量重置为 0 了,将其赋值为 next[k] 就行。

 

本文只是简单的描述下KMP以备忘,更详细的分析说明可以见网上大神们的博客

 

using namespace std;
const int maxn = 1000020;
char src[maxn],substring[maxn];
int nxt[maxn];
void get_nxt(char* substring)
{
	int substring_len = strlen(substring);
	memset(nxt, 0, sizeof(nxt));
	nxt[0] = -1;
	int j = -1;
	for(int i = 1; i < substring_len; i++)
	{
		while(j > -1 && substring[i] != substring[j + 1])
			j = nxt[j];
		if(substring[j+1] == substring[i])
			j = j + 1;
		nxt[i] = j;
	}
}

//process src & substring to get the position
int kmp(char* src, char* substring)
{
	int j = -1;
	int ans = 0;
	int substring_len = strlen(substring);
	int src_len = strlen(src);
	for(int i = 0; i < src_len; i++)
	{
		while(j > -1 && src[i] != substring[j + 1])
			j = nxt[j];
		if(src[i] == substring[j + 1])
			j++;
		if(j == substring_len -1)
		{
			ans ++;
	        printf("From position %d to position %d\n", i + 2 - substring_len, i+1);
			j = nxt[j];
		}
	}
	return ans;
}

  

 

http://blog.csdn.net/v_july_v/article/details/7041827

 

转载于:https://www.cnblogs.com/py100/p/4386616.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值