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

    关于KMP算法,看了很多博客,自己也做了一些字符串匹配之后,总算弄懂一些了,但是可能还要进一步深入研究,先写一部分吧,这部分足够应对笔试的nextval和next问题了。

    关于如何求next:

    先给出一个字符串“ababaabab”

        j         1  2  3  4  5  6  7  8  9

        i         a  b  a  b  a  a  b  a  b

      next     0  1  1  2  3  4  2  3  4

    nextval   0  1  0  1  1  4  1  0  1

    next怎么求呢:

    首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。

    "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,

      - "A"的前缀和后缀都为空集,共有元素的长度为0;

      - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;

      - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;

      - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;

      - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;

      - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;

      - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

    其实在我看来,撇开这个next值在KMP中的正式含义,如果要便于理解,你可以看做后缀中跟前缀的最长共有元素,我们要求的就是这个共有元素加上轮到的字符,得到“最终串”,然后看“最终串”有多长(其实就是看最后一位的位置,变相求字符串长度),就是所求的next值。

    关键是理解我说的共有元素,要理解我说的通俗的共有元素,就要看懂上面对前缀和后缀以及“部分匹配值”,所以先看懂啥是共有元素后,再继续往下,我相信你一定能学会。

    我个人是很讨厌各种专业名词混杂的博客的,十分不方便理解,所以我尽量用通俗的方式来解释。

    我们先看到第一个字符a,此时j=1,求的是next(1)。next(1)为该字符串的第一个字符,它之前没有别的字符,所以不用比较,所以为0。

    接着是轮到第二个字符b, 此时j=2,求的是next(2)。next(2)为该字符串的第二个字符,它之前的字符串为“a”,a中没有重复的字符,所以共有元素为空,那么加上轮到的字符“b”,得到的“最终串”为“b”,长度为1,且,那next(2)= 1。

    总之,不管前两位是什么,next(1)、next(2)都固定为 0、1。

    轮到第三个字符a了,它前面是字符串“ab”,很明显字符串“ab”中不含重复字符,所以共有元素为空,那么加上轮到的字符“a”,得到的“最终串”为“a”,长度为1,且,那next(3)= 1。

    轮到第四个字符b了,它前面是字符串“aba”,很明显字符串“aba”中含重复字符,共有元素为“a”,那么加上轮到的字符“a”,得到的“最终串”为“b”,长度为2,且,那next(4)= 2。

    轮到第五个字符a了,它前面是字符串“abab”,很明显字符串“abab”中含重复字符,共有元素为“ab”,那么加上轮到的字符“a”,得到的“最终串”为“aba”,长度为3,且,那next(5)= 3。

    轮到第六个字符a了,它前面是字符串“ababa”,这时,你要是不理解上面的前缀后缀,我觉得你就嗝屁了,字符串“ababa”存不存在共有元素呢?有的话,是什么呢?"ababa"的前缀为[a, ab aba, abab],后缀为[a,ba,aba,baba],这下看得出来了吧,共有元素取最长是“aba”,加上第六个字符a,最终串为“abaa”,所以next(6)= 4。

    以此类推,应该没问题吧,关键是搞懂前缀和后缀。

    那么next讲完,我们再来说说nextval,看了贼多关于nextval的求法,真的脑袋疼,最后我找到了一个我特别喜欢的,这里跟大家分享一下:

    关键在于只看前面有重复字母的几位就可以。

    比如上面这个字符串ababaabab吗,我们复制粘贴一下,这样方便大家看:

    先给出一个字符串“ababaabab”

        j         1  2  3  4  5  6  7  8  9

        i         a  b  a  b  a  a  b  a  b

      next     0  1  1  2  3  4  2  3  4

    nextval   0  1  0  1  1  4  1  0  1

    这里我们已经能熟练求出next了,这时候其实工程已经完成一大半了,接下来就是我跟你们说的关键——只看前面有重复字母的,其余跟next一样:

    可见从第三位开始都有重复字母,那么前两位nextval就是0、1了,好,我们开始从第三位开始求:

    第三位是“a”,它的next值为1,就找字符串的第1位字符,是“a”,一样,那就把这个a的nextval值改为后面这个“a”的next值 0 。

    第四位是“b”,它的next值为2,就找字符串的第2位字符,是“b”,一样,那就把这个a的nextval值改为后面这个“b”的next值 1 。

    第五位是“a”,它的next值为3,就找字符串的第3位字符,是“a”,但第三位的这个a之前做过处理,所以就把第五位的这个a的nextval值改为第一个“a”的next值 0。

    第六位是“a”,它的next值为4,就找字符串的第4位字符,是“b”,诶!不一样,这时候就把nextval等于next就行,所以第六位的next值 为4 。

    以此类推。

    最后是KMP算法的原理,就是KMP匹配串如何移动,每次移动多少的问题。这一块我觉得有个博客写的比我好很多,在这里贴出来,我觉得写的已经十分通俗易懂了。关于前缀后缀和共有元素部分我也略有借鉴,感谢这位博主。

    http://www.cnblogs.com/c-cloud/p/3224788.html

  • 相关阅读:
    Compression algorithm (deflate)
    tcpip数据包编码解析(chunk and gzip)_space of Jialy_百度空间
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    gzip压缩算法: gzip 所使用压缩算法的基本原理
    Decompressing a GZip Stream with Zlib
    Frequently Asked Questions about zlib
    how to decompress gzip stream with zlib
    自己动手写web服务器四(web服务器是如何通过压缩数据,web服务器的gzip模块的实现)
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    C语言抓http gzip包并解压 失败 C/C++ ChinaUnix.net
  • 原文地址:https://www.cnblogs.com/Misakikure/p/9755578.html
Copyright © 2011-2022 走看看