KMP思想简述

本文深入浅出地介绍了KMP算法的原理与实现过程,并通过实例分析展示了如何利用模式串的特性提高字符串匹配效率。

首先推荐matrix的博文KMP博文

    我们如何在一个输入字符串中匹配一个模式串呢?
    首先,我们可能想到最简单的方法:
    string S;               // 假设 S的长度为m
    string pattern;         // 假设 pattern的长度为n
    int i = 0, j = 0;
    while ( 1 ) {
        if (S[j+i] == pattern[j])
            j++;
        else {
            i++;
            j = 0;   // 这里,如果不匹配发生,我们永远从模式串头开始匹配。
        }
        if (i >= S.size())
            return false;
        if (j == pattern.size() )
            return true;
    }
    (这里我还是觉得换成两个for循环最直观)
    我们分析一下上面解法的复杂度。让我们分析一下最极端的情况,我们每次都匹配到模式串的倒数第一位
    当我们要匹配最后一位时,发现不匹配,这时我们经历了n-1步。
    这时,我们让j指针回到头,让i指针后移一位,开始匹配。极端情况下,每一次都是这种情况,复杂度为O(mn)

    我们举个例子:
        假设我们的输入串为aaaaaaaaaaaaaaaa...
        我们的模式串为aab
        这时,我们感觉被忽悠了,一看就不可能匹配上呀,没错,但是计算机要一步步傻乎乎的执行到最后才知道。

    怎么办?我们如何改进我们的算法?
    我们考虑一个模式串的例子:
        abaaba
    我们来观察一下这种模式串的pattern
    发现aba既是前缀,又是后缀。这个性质可太好了,为什么好呢? 
    例如我们的输入串为abaabccc,我们来模拟一下匹配的过程

    aabaabacc
    abaaba
    ^
    aabaabacc
     abaabab 
     ^

    aabaabacc
     abaabab
       ^
    aabaabacc
     abaabab
        ^
    
    aabaabacc
     abaabab
         ^
    
    aabaabacc
     abaabab
          ^

    当我们看下一个字符的时候,c和b不匹配怎么办?
    我们需要把j指针移到最开头吗?
    当然不需要了!
    
    aabaabacc
        abaabab
          ^ 
    
    只需要移动到这里就行了!
    为什么可以呢?
    因为模式串的匹配前缀为abaaba时,aba既是前缀也是后缀,这时候,我们只需要把j指针移动到这个
    既是前缀又是后缀的串的末尾就行了,从下一个开始匹配就可以减少我们的计算量了。

    这时候又有一个问题,如果有很多既是前缀又是后缀的串,j指针回到哪呢?
    当然是最长的串的末尾了!!!(有谁想多匹配几次做无用功呢?)

    这样,我们就已经推出大名鼎鼎的KMP算法了!!!

    KMP算法分为两步,预处理和匹配
    预处理时实际上是找模式串中每个位置i之前的最长既是前缀又是后缀串的长度。
    这就类似于动态规划的思想了。(两个指针算不算双指针呢?)

    匹配时,就按照我们已经构建好的失配指针,让j指针移动到该有的位置就好了。

    我们再来看一下复杂度,由于在匹配时,我们只需要一遍扫描输入串的复杂度即可,在预处理时扫描一遍模式串
    所以一共为O(m+n)。

    KMP思想就是这么简单!

    拓展:如果了解了KMP的思想,那么多模式串匹配也就容易了,无非就是从一个链变成一个树了吗(trie树)
    有兴趣的小伙伴可以马上去了解一下多模式串匹配,真的非常相似哟~
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值