zoukankan      html  css  js  c++  java
  • 详解又详解KMP中的next和nextval的算法

    一、定义

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。


    二、图解原理

    以下借用http://www.cnblogs.com/c-cloud/p/3224788.html的部分内容 
    这种算法不太容易理解,网上有很多解释,但读起来都很费劲。直到读到这篇文章,我才真正理解这种算法。下面,我用自己的语言,试图写一篇比较好懂的KMP算法解释。

    1.这里写图片描述

    首先,字符串”BBC ABCDAB ABCDABCDABDE”的第一个字符与搜索词”ABCDABD”的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。

    2.这里写图片描述

    因为B与A不匹配,搜索词再往后移。

    3.这里写图片描述

    就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。

    4.这里写图片描述

    接着比较字符串和搜索词的下一个字符,还是相同。

    5.这里写图片描述

    直到字符串有一个字符,与搜索词对应的字符不相同为止。 
    当空格与D不匹配时,你其实知道前面六个字符是”ABCDAB”。KMP算法的想法是,设法利用这个已知信息,不要把”搜索位置”移回已经比较过的位置,继续把它向后移,这样就提高了效率。

    6.这里写图片描述

    因为空格与C不匹配,搜索词还要继续往后移。

    7.这里写图片描述

    逐位比较,直到发现C与D不匹配。于是,继续将搜索词向后移动。

    8.这里写图片描述

    逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。


    三、详解

    标号(j) 1 2 3 4 5 6 7
    模式串(P) A B C D A B D

    1、KMP算法的核心思想

    ——就是回溯到存在”对称“的地方。

    • 注意,这里的“对称”不是指ABCCBA,而是指例如”ABCABC”中队前队尾都分别有1个”ABC”,又例如”ABCCCCCAB”中队前队尾都分别有一个”AB”。

    2、看图说话

    从第2部分图中可以分析得出,当扫描到模式串中某一位发现不匹配,总是回溯到在这一位之前的部分模式串存在重复的地方

    • 例如2.5中找不到字母D(标号4),D之前串为”ABCDAB”,存在队前队尾重复”AB”(2个字符),因此退回到队首的“AB”后一位C(标号3)。
    • 例如2.6中找不到字母C(标号3),C之前串为”AB”,不存在重复的(0个字符),因此退回到队首最前面(标号1)。

    所以,next(j)就是当模式串第j位不匹配时即将要退回到的字母标号

    • 以上例子也可以看出,如果有2个字符重复,就退到第3位,如果有0个字符重复,就退到第1位。显然这是一个+1的关系。

    3、next计算过程

    不管第一位和第二位是什么,第一位next(1)=0,第二位next(2)=1,这是固定的。

    当j=3时,P(j)=C,C之前有”AB”,不存在重复(0位),所以next(3)=0+1=1; 
    当j=4时,P(j)=D,C之前有”ABC”,不存在重复(0位),所以next(4)=0+1=1; 
    当j=5时,P(j)=A,C之前有”ABCD”,不存在重复(0位),所以next(5)=0+1=1; 
    当j=6时,P(j)=B,C之前有”ABCDA”,存在重复”A”(1位),所以next(6)=1+1=2; 
    当j=7时,P(j)=D,C之前有”ABCDAB”,存在重复”AB”(2位),所以next(7)=2+1=3;

    4、nextval=对next的优化

    观察第5位”A”,当它不匹配时,按照next行回溯到标号1也为字母A,这时再匹配A是徒劳的,因为已知A不匹配,所以就继续退回到标号1字母A的next(1)=0。为了直接点进行优化,就有了nextval行:

    • 只看前面有重复字母的几位就可以。

    j=5,P(5)=A,next(5)=1,P(1)=A=P(5),所以nextval(5)=next(1)=0; 
    j=6,P(6)=B,next(6)=2,P(2)=B=P(6),所以nextval(6)=next(2)=1; 
    j=7,P(7)=D,next(7)=3,P(3)=C!=P(7),所以nextval(7)=next(7)=3;


    结果:

    标号(j) 1 2 3 4 5 6 7
    模式串(P) A B C D A B D
    next 0 1 1 1 1 2 3
    nextval 0 1 1 1 0 1 3

    详解完毕,希望大家喜欢。

    原文 https://blog.csdn.net/nanami809/article/details/49367159

  • 相关阅读:
    HDU 2639 Bone Collector II (01背包,第k解)
    POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
    hihoCoder #1165 : 益智游戏 (挑战赛11 B题)
    UVA 562 Dividing coins 分硬币(01背包,简单变形)
    POJ Charm Bracelet 挑饰品 (常规01背包)
    hiho一下 第四十四周 博弈游戏·Nim游戏(直接公式解)
    UVA 624 CD(01背包,要记录路径)
    118 Pascal's Triangle 帕斯卡三角形 杨辉三角形
    117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II
    116 Populating Next Right Pointers in Each Node 每个节点的右向指针
  • 原文地址:https://www.cnblogs.com/hiszm/p/12384985.html
Copyright © 2011-2022 走看看