• KMP算法总结


    KMP

    窗外的麻雀,在电线杆上多嘴~~

      ta说这一句,很有寒假的感觉~

    首先

    #define ls 母串长度

    #define lt 子串长度

    在这寒假即将到来之际(2017.1.14),我们学习了KMP算法

    KMP算法,异常nb的字串匹配算法

    关于字串匹配,我们最开始都是(ls*lt)的暴力

      *超时稳稳的

    具体就是枚举每个起点,然后起点往后推lt长度来比较是否一样

    实在是太慢了

      所以,人们开发了KMP算法

    KMP是怎么来弄的时间复杂度的呢?

    不急,一步一步慢慢讲(记录子串靠后的元素的部分前缀在在子串中从0开始的位置)

    KMP的关键在于next数组

    next数组是什么呢?

    next数组记录的是子串靠后的元素的部分前缀在子串中从0开始的位置

    有点难理解,我们来分析一下

    a b c a b d

    它对应的next数组的值是

    a b c a b d

    0 0 0 1 2 0

    你会发现子串前三个元素(abc)之后还有两个已经出现的元素(ab)

    所以,(ab)中的a可以对应(abc)中的a,它的next值是1

    (ab)中的b可以对应(abc)中的b,它的next值是2

    附求next代码:

    inline void GetNext()
    {
        int k=-1,j=0;
        next[j]=k;
        while(j<lt)
        {
            if(k==-1||t[j]==t[k])
            {
                k++,j++;
                next[j]=k;
            }
            else k=next[k];
        }
    }

    然后,我们就可以利用这个来优化

    怎么优化呢?

    两个指针i,j

    i表示当前在母串中的位置

    j表示当前在子串中的位置

    刚开始i,j的初始值都是0

      然后,当s[i]==t[j](当前位置的数匹配)时,i++,j++,开始下一个位置的匹配

    然后当i!=j时,即不匹配时,我们开始从j往前回溯

    怎么回溯呢

    j=next[j]

    然后我们的时间就被优化了(仔细思考会发现是个线性的复杂度ls+lt)

    附kmp代码:

    inline int Kmp()
    {
        //求出现的次数
        GetNext();
        int i=0,j=0,return_=0;
        while(i<ls)
        {
            if(j==-1||s[i]==t[j]) i++,j++;
            else j=next[j];
            if(j==lt)
            {
                j=next[j];
                return_++;
            }
        }
        return return_;
    }

    现在说两道关于kmp的裸题:

      洛谷 3375

      poj 3461(有点小坑)

  • 相关阅读:
    div显示和隐藏
    C语言求素数的算法
    日志分析概述
    Base64编码 概念和用途
    leetcode
    hdu2665-Kth number
    为什么要新加入的人不闻不问?
    实现微博@@@
    JAVA运行程序代码段
    IfSpeed 带宽计算
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6286152.html
Copyright © 2020-2023  润新知