码迷,mamicode.com
首页 > 编程语言 > 详细

KMP算法学习

时间:2017-09-17 20:07:57      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:开始   字符   学习心得   最大   string   后缀   class   添加   下标   

最近在看算法,觉得kmp算法的一些学习心得可以记录一下。

我本身是在看《算法》的,里面介绍kmp算法时,实在看的一脸懵逼,就看了别人的心得,这里推荐2篇博文:

1.阮一峰大大的:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

2.实现1中求next的博文:http://www.cnblogs.com/c-cloud/p/3224788.html

根据1文我实现了kmp,但留空next的求法,毕竟1文也只是大概说了next的意义,对2文我在自己的理解上也自己实现了一波,觉得更加容易懂些吧。

个人添加的理解(也都在注释里了):

  1.next的本质是最长共同前缀后缀,然后在匹配失败时,指向模板字符串的指针直接重置为next[k-1](即重置到最长共同前后缀的下一个位置),而长字符串的指针勿需动,即相当于指针新位置前的那一坨已经匹配成功了,接着从新指针那里匹配下去即可

  2.(参考下面代码)计算next时,如果p[i]=p[k]则共同前后缀+1,不等则在已经匹配成功的部分p[0~k-1]中找最大共同前后缀next[k-1],然后继续比较p[i]和p[新k],如果k<=0即得不到已经存在的next的帮助了,这时k=0,即木有共同前后缀了。

// next的本质是最长共同前缀后缀,然后在匹配失败时,指向模板字符串的指针直接重置为next[k-1],而长字符串的指针勿需动,即相当于指针新位置前的那一坨已经匹配成功了,接着从新指针那里匹配下去即可
    void CalculateNext(string pattern, ref int[] next)
    {
        next[0] = 0;
        for (int i = 1, k = 0; i < pattern.Length; ++i)
        {
            while(pattern[i] != pattern[k])
            {
                if (k > 0)
                    k = next[k - 1];//这个有点难理解,因为她是匹配失败后(p[i]!=p[k]),
                                    //直接使用匹配成功部分的共同前后缀接着进行匹配p[i]和p[新k],此时因为新k=next[k-1],所以p[x~i]=p[0-新k]
                else
                {
                    k = -1;//得不到前面next的帮助了,需要置k=0,并且需要跳出while
                    break;
                }
            }

            k++;
            next[i] = k;
        }
    }

    void KMP(string inStr, string pattern, int[] next)
    {
        for (int i = 0, k = 0; i < inStr.Length; i++)
        {
            if (pattern[k] == inStr[i])
            {
                k++;
                if (k == pattern.Length)
                {
                    break;
                }
            }
            else
            {
                if (k != 0)//k=0特殊处理,直接移动i即可,k依然是0
                {
                    k = next[k-1];//一开始我是用1文的说法(移动位数 = 已匹配的字符数 - 对应的部分匹配值):pattern右移d=k-next[k-1],即k需回退x才能维持和i对应(分别对着两字符串的下一个比较字符),x=k-d=next[k-1]
                    //即,k=next[k-1],所以理解为:k应该重置到最长共同前后缀的下一个位置,这样比1文的说法容易理解些(因为next里是长度,k是下标,所以刚好next[k-1]就是最长共同前后缀的下一个位置的下标) } } } }

 

KMP算法学习

标签:开始   字符   学习心得   最大   string   后缀   class   添加   下标   

原文地址:http://www.cnblogs.com/Tearix/p/7536744.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!