zoukankan      html  css  js  c++  java
  • KMP算法学习

    最近在看算法,觉得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]就是最长共同前后缀的下一个位置的下标) } } } }
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/Tearix/p/7536744.html
Copyright © 2011-2022 走看看