[算法]KMP算法

这个字符串匹配的算法很著名,也很难理解。

研究了半天,也算看了不少博客,基本上要讲的,要理解的,各大博客大神都已详述。

我把主要几篇给我很大启迪的文章列下,也给自己往后复习留下点踪迹。

1、字符串匹配的KMP算法 http://kb.cnblogs.com/page/176818/
这篇文章,看完后很快就知道KMP算法在干什么,以及我们的核心任务是什么?

2、KMP算法的Next数组详解 http://www.cnblogs.com/tangzhengyue/p/4315393.html
这篇博客讲解的是我看的最懂的一篇。

3、KMP算法详解 http://blog.csdn.net/joylnwang/article/details/6778316
很详细,作者很厉害,不过我个人而言看的累了点,在阅读第二篇后,有节选的阅读了这篇,很受启发。next[]和f()区别,为什么要用next[]。就是下面这两段:

现在,我们来总结一下next[j]和f(j)的关系,next[j]是所有满足pattern[1…k - 1] = pattern[(j - (k - 1))…j -1](k < j),且pattern[k] != pattern[j]的k中,k的最大值。而f(j)是满足pattern[1…k - 1] = pattern[(j - (k - 1))…j -1](k < j)的k中,k的最大值。还是以上例的模式来说,对于第7个元素,其f(j) = 4, 说明pattern[7]的前3个字符与模式的前缀3相同,但是由于pattern[7] = pattern[4], 所以next[7] != 4。

通过以上这些,读者可能会有疑问,为什么不用f(j)直接作为KMP算法的跳转表呢?实际从程序正确性的角度讲是可以的,但是使用next[j]作为跳转表更加高效。还是以上面的模式为例,当target[n]与pattern[7]发生匹配失败时,根据f(j),target[n]要继续与pattern[4]进行比较。但是在计算f(8)的时候,我们会得出pattern[7] = pattern[4],所以target[n]与pattern[4]的比较也必然失败,所以target[n]与pattern[4]的比较是多余的,我们需要target[n]与更小的pattern进行比较。当然使用f(j)作为跳转表也能获得不错的性能,但是KMP三人将问题做到了极致。

4、再补充一个 http://blog.csdn.net/yutianzuijin/article/details/11954939

谢谢以上大神的博客。

自己总结了下代码,仅供参考。

int* BuildNext(string pattern)
{
    int n = pattern.size();
    int* next = new int[n]; //next数组存放跳转链表
    int j = 0;
    int k = -1;
    next[0] = -1;//首位为-1
    while(j < n-1)
    {
        if(k == -1 || pattern[j] == pattern[k])
        {
            if(pattern[j+1] == pattern[k+1])
            {
                next[++j] = next[++k];
            }
            else
                next[++j] = ++k;
        }
        else
        {
            k = next[k];
        }
    }
    return next;
}
int Search(string pattern,string original)
{
    int *next = BuildNext(pattern);
    int n = original.size();
    int j = 0;
    int pos = -1;//存在返回地址,不存在返回-1
    for(int i = 0;i<n;i++)
    {
        while(j > 0 && original[i] != pattern[j])
        {
            j = next[j];
            if(j == -1) //因为我的数组是从0开始的,所以设置初始为-1,其实还是从第一位开始比较,设置下,以防后面越界。
                j = 0;
        }
        if(original[i] == pattern[j])
            j++;
        if(j == pattern.size())
        {
            pos = i - j+1;//此时返回的其实是最后一个匹配成功的字符串的位置。可以加break选择跳出
            j = next[j-1];//数组最后一位是next[j-1]。
        }
    }
    return pos;
}
void main()
{
    string pattern = "abcabcacab";
    string original = "babcbabcabcaabcabcabcacabc";

    int pos = Search(pattern,original);

    cout<<pos;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值