您的位置:首页 > 其它

kmp算法总结

2012-06-28 15:19 260 查看
  最近看了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数组的求解过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 string