字符串匹配查找算法-KMP

来源:互联网 发布:程序员需要数学好吗 编辑:程序博客网 时间:2024/06/09 23:37
KMP的思路在于跳转,有效率的跳转可以减少很多不必要的比较。
而用于跳转依据的表称为跳转表,也叫next[]数组

next[]数组生成的依据就是“尽量可能不让步”的思想。。。
例如A字符串和B字符串比较,我们会让B的开头和A的第一位比较,当遇到不一样的时候,我们不会“ 不让步”,而是让B的开头和A的第二位开始重新做匹配比较。

这显然不合理。这是完全不考虑“不让步”的做法

还一种极端的情况,也是最难理解的情况,就是“完全不让步”。

如: 
ABCDEF中查找ABD

第一次匹配的时候,是ABCDEF的第一位和ABD的第一位开始做匹配,当匹配到第三位的时候发现不一样了(ABCEF的第三位是C,ABD的第三位是D)。。。这个时候“完全不让步”的话,下一跳因为是让ABCDEF的第四位D与ABD的第一位A开始比较。这种极端的“大跳跃”在这种情况也是不合理的做法。

所以研究【如何正确的跳转】正是next[]数组的所要做的事情。

next[]数组是根据【查找数组】算出来的,比如ABCDEF与ABD做查找的话,我们认为ABCDE是【被查找数据】,ABD就是【查找数组】


例如:根据ABD和下面的【生成next算法】,我们可以口算出next[]=[0,1,1]或[-1,0,0]或者是[-2,1,1]或者是[-3,2,2].......

【生成next算法】
求【查找数组】某一位的next值:
如果
    前面第n字母和开头第一个字母一样,后面紧接的一串也一样(前面第n个~到自己的位置),那么为next[j]=n+1
    (让n步表示:当前位不一样,重新从【下一位的前n位】开始比较)
否则
    开头不一样的为next[j]=1(让1步表示:当前位不一样,重新从【下一个位的前1位(即当前位)】开始比较)
    开头一样的为next[j]=0(不让步表示:当前位不一样,就下一位开始重新比较)



思路:
怎么减少匹配次数?(用跳转)------》怎么快速跳转?(用跳转表)------》怎么求跳转表?(求出每一位的next[]值)
-----》怎么求某一位的跳转值?(后面的字符跟前面的是否存在子串)

第一种情况:如果
  被求next值的该位 前面第n字母和开头第一个字母一样,后面紧接的一串也一样(前面第n个~到自己的位置),那么为next[j]=n+1
    (让n步表示:当前位不一样,重新从【下一位的前n位】


第二种情况:被求next值的该位和开头不一样的为next[j]=1(让1步表示:当前位不一样


第三种情况:被求next值的该位 开头一样的为next[j]=0(不让步表示:当前位不一样,就下一位开始重新比较)
0 0