美文网首页
数据结构和算法回顾-kmp

数据结构和算法回顾-kmp

作者: wangzun | 来源:发表于2015-10-12 15:59 被阅读0次

KMP字符串查找算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新检查先前匹配的字符。

*此算法的核心是跳过肯定无法匹配的部分,达到高效匹配的目的。 *

这里有一个可能很清晰介绍kmp的blog, 不过没有代码实现,也没有讲原因。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
 * 字符串模式匹配 之 BF算法
 * Author : Yonggang Yuan
 */
#define EOS '\0' // End Of String
int main() {
    char text[] = "s a good,Yonggang Yuan is a good student, is a good student twice ... is a good";
    char m[] = "s a good";
    int i, lenOfM = strlen(m);
    for( i=0; *(text+i) != EOS; i++ ) {
        if( memcmp(m, text+i, lenOfM) == 0 ) {
            printf("Match m at %d\n", i);
        }
    }

    return 0;
}
  • 前后缀
    一个字符串 ABCABKKJSCNABCAB
    前后缀为: 1)AB 2)ABCAB
    最大前后缀为: ABCAB
  • 跳过哪一部分
    移动位数 = 已匹配的字符数 - 对应的部分匹配值
    部分匹配值就是最大前后缀
    下面有两个字符串
串a A B C A B K K J S C N A B C A B
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

|串b |A|B|C|A|B|D|F|
|---|-|-|-|-|-|-|-|-|
|j|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|

在a[i=5],b[j=5]时候失配,按照kmp算法,下一步就应该串b就应该向右移动(已匹配数-最大前后缀),用代码表示就应该为i不变,j=next[j-1]。
怎么理解j=next[j-1]?
next是字符串b的最大前后缀大小值组成的数组,比如子串b[0~5]的最大前后缀为AB,值也就为2,所以next[4]=2。而j=next[j-1]就表示j的下标变为b[j]前面的字符串的最大前后缀,

上面这个例子可以用下图表示

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
串a A B C A B K K J S C N A B C A B
串b A B C A B D F
j 0 1 2 3 4 5 6 7

从i[5],j[2]开始重新匹配,相对于暴力匹配法跳过i[12],由于i[34]与j[0~1]必然相等,也被忽略。

为什么i[1~2]可以直接跳过,会不会从i[1],j[0]开始直接匹配上了,那我来看看这情况,如下图

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
串a A B C A B K K J S C N A B C A B
串b A B C A B D F
j 0 1 2 3 4 5 6 7

因为在i[5],j[5]处失配,所以i[5]应该和什么匹配未知,已知的条件不能判断,而用已知条件只要证明i[14]与j[03]绝对不匹配就行了,
已知条件:
1)i[04]与j[04]已经匹配上了
2)next数组(看做已知的,后面在详细求解)
如果上图的情况能匹配上,那么i[14]=j[03],又已知i[14]=j[14],所以j[03]=j[14]所以j[03]和j[14]是j[04]的前后缀,然而ABCAB的最大前后缀是AB值为2,已经矛盾了,所以i[14]与1[0~3]绝对不匹配,可以跳过。

  • next数组
    next[k]也就是字符串b[0~k]的最大前后缀,数组求法有点像数学归纳法,首先我们知道next[0]=0,然后递归求取next[1],next[2]...next[n]。
    一步步来看,先判断b[1]和b[0]是不是相等,如果相等那b[0],b[1]就为b[0~1]的前后缀
  • golang代码实现
func KmpMatch(astring string, bstring string) int {
        i, j := 1, 0
        next := make([]int, len(bstring))
        next[0] = 0
        for i < len(bstring) {
                if bstring[i] == bstring[j] {
                        next[i] = j + 1
                        i++
                        j++
                } else if j == 0 {
                        next[i] = 0
                        i++
                } else {
                        j = next[j]
                }
        }
        i, j = 0, 0
        for i < len(astring) {
                if astring[i] == bstring[j] {
                        if j == len(bstring)-1 {
                                return i
                        }
                        i++
                        j++
                } else {
                        if j > 0 {
                                j = next[j-1]
                        } else {
                                j = 0
                                i++
                        }
                }
        }
        return 0
}

相关文章

  • KMP算法及优化

    转载请注明出处: KMP算法及优化 今天看到同学在复习数据结构书上的KMP算法,忽然发觉自己又把KMP算法忘掉了,...

  • 数据结构和算法回顾-kmp

    KMP字符串查找算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新...

  • KMP算法

    此文是严蔚敏的数据结构课程有关KMP算法相关课程 - KMP算法讲解P12[https://www.bilibil...

  • 数据结构与算法---KMP算法

    KMP算法是数据结构与算法中串的经典算法案例,KMP是由三位学者同时发现(D.E.Knuth,J.H.Morris...

  • KMP算法详解

    在数据结构课上老师讲了kmp算法,但当时并没太懂,现在把思路重新理一遍。 1.kmp算法简介 KMP是三位大牛:D...

  • KMP算法文章合集

    字符串的查找:朴素查找算法和KMP算法 暴力匹配算法与KMP算法(串的匹配) 字符串查找算法BF和KMP 字符串匹...

  • 字符串匹配

    BF 算法和 RK 算法BM 算法和 KMP 算法

  • KMP 专题整理

    KMP 学习记录 kuangbin专题十六——KMP KMP 学习总结 朴素 KMP 算法 拓展 KMP 算法(E...

  • (原创)大白话KMP算法详解,一秒get模式匹配

    引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两...

  • 对KMP算法的一些理解

    最近学到KMP算法,下面讲讲对KMP算法的一些个人理解,希望对大家有帮助! 对于KMP算法的理解: 整个KMP算法...

网友评论

      本文标题:数据结构和算法回顾-kmp

      本文链接:https://www.haomeiwen.com/subject/efqocttx.html