zoukankan      html  css  js  c++  java
  • 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(有点小坑)

  • 相关阅读:
    Mybatis学习01:利用mybatis查询数据库
    SpringBoot_登录注册
    python抓取中科院大学招聘
    centos7设置固定IP
    PIL给图片加水印
    You can ignore those files in your build.gradle
    mysql事件执行时间
    wampserver2.5域名解析错误问题
    Mysql错误消息 语言设置
    js控制select多选
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6286152.html
Copyright © 2011-2022 走看看