kmp算法总结

  最近看了kmp算法,经过反复的学习终于感觉完全弄懂了kmp算法,现做一个小结。

  kmp算法在进行字符串匹配的时候,如果当前位置j匹配不成功,那么模式串向前移动的位数由next[j]的值决定。next数组的位置j的值表示的是模式串p中p[0~j-i]子串的前缀和后缀相匹配的最长长度,即如果next[j]=k,表示p[0~k-1]==p[j-k~j-i],而且p[k]!=p[j]。

next数组的值有三类:

  • -1:表示j为0或者不存在前后缀相等的子串,而且p[j]==p[0]。这个情况在匹配失效的时候,下一步应该将目标串当前位置加一和模式串的第一个位置比较
  • 0:表示不存在前后缀相等的情况,但是p[0]!=p[j]。这个情况在匹配失效时,下一步将目标串当前比较位置与模式串的第一个位置比较(这个时候和上一个不同在于,p[0] != p[j]要求从目标串的当前位置比较)
  • k(k>0):表示存在最大长度为k的前缀后缀字串相匹配。这个情况下,下一步将目标串当前位置与模式串的第k+1个位置比较,即与p[k]比较。

  next值的求解代码为:

void getNext(const string str,vector<int>& next)  
{  
    next[0] = -1;  
    int j = -1;  
    for(size_t i = 0;i < str.size()-1;)  
    {  
        if (j == -1 || str[i] == str[j])//j表示当要计算next[i+1]时str[0...i-1]前后缀相等的子串的最长长度(-1代表没有相等的前后缀,计算next[i+1]使用了前面的信息  
        {  
            ++i;  
            ++j;  
            if (str[i] != str[j])  
                next[i] = j;  
            else  
                next[i] = next[j];  
        }  
        else  
            j = next[j];  
    }  
}


kmp算法代码如下所示:

int kmp(const string src,const string pattern)
{
	vector<int> next(pattern.size());
	getNext(pattern,next);
	
	for (int i = 0;i < next.size();i++)
		cout << next[i] << " ";
	cout << endl;
	int i = 0;
	int j = 0;
	while (i < src.size() && j < pattern.size())
	{
		if (src[i] == pattern[j])
		{
			++i;//注意,这里最后一次匹配成功了仍然会加一,所以在最后返回的时候不用加一		
			++j;
		}
		else if (next[j] == -1)
		{
			++i;
			j = 0;
		}
		else
			j = next[j];
	}
	if (j >= pattern.size())
		return i - pattern.size();
	else
		return -1;
}
以上就是KMP算法的完整实现。要理解kmp算法,关键是理解next数组值的含义,还有next数组的求解过程。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值