• 如何借助BM算法轻松理解KMP算法


      KMP 算法是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Pratt)的名字来命名的,算法的全称是 Knuth Morris Pratt 算法,简称为 KMP 算法。

      KMP 算法的核心思想,跟上一节讲的BM算法非常相近。我们假设主串是 a,模式串是 b。在模式串与主串匹配的过程中,当遇到不可匹配的字符的时候,我们希望找到一些规律,可以将模式串往后多滑动几位,跳过那些肯定不会匹配的情况。

      这里我们可以类比一下,在模式串和主串匹配的过程中,把不能匹配的那个字符仍然叫作坏字符,把已经匹配的那段字符串叫作好前缀。

      KMP 算法的时间复杂度是 O(n+m)。其中求next数组(失效函数)比较难理解,建议阅读大话数据结构p139的例子。

    C++版代码如下

    #include <iostream>
    #include <math.h>
    #include <cstring>
    using namespace std;
    
    #define MAXNUM 256
    
    // 朴素字符串匹配
    // 查找子串b在主串a中第pos个字符之后的位置,其中0<= pos <= n-1
    int indexBasical(char a[], int n, char b[], int m, int pos){
        int i = pos;
        int j = 0;
        while(i < n && j < m){
            if(a[i] == b[j]){
                i++;
                j++;
            }
            else{
                i = i - j + 1;
                j = 0;
            }
        }
        if(j >= m)
            return i - m;
        else
            return -1;
    }
    
    // KMP匹配算法
    // 计算next失效函数
    void getNext(char b[], int m, int next[]){
        int i, j;
        i = 0;
        j = -1;
        next[0] = -1;
        while(i < m - 1){
            if(j == -1 || b[i] == b[j]){
                i++;
                j++;
                next[i] = j;
            }
            else{
                // 若字符不相同,则j值回溯
                j = next[j];
            }
        }
    }
    
    int indexKMP(char a[], int n, char b[], int m, int pos){
        int i = pos;
        int j = 0;
        int next[MAXNUM];
        memset(next, 127, sizeof(next));
        getNext(b, m, next);
        while(i < n && j < m){
            // 相对于BF(朴素匹配)算法增加了j=-1判断
            if(j == -1 || a[i] == b[j]){
                i++;
                j++;
            }
            else
                // 相对于BF算法,i并不会回溯,并且j不会退回到0,而是退回到合适的位置
                j = next[j];
        }
        if(j >= m)
            return i - m;
        else
            return -1;
    }
    
    
    int main()
    {
        int next[MAXNUM];
        memset(next, 127, sizeof(next));
        char a[10] = "oodgoogle";
    
        memset(next, 127, sizeof(next));
        char c[7] = "google";
        getNext(c, 6, next);
    
        // BF算法
        cout<<indexBasical(a, 9, c, 6, 0)<<endl;
        // KMP算法
        cout<<indexKMP(a, 9, c, 6, 0);
        return 0;
    }
    
  • 相关阅读:
    不通过App Store,在iOS设备上直接安装应用程序(转)
    Quest Central for DataBase 5.0.1,6.1 (软件+注册)
    微信公众号自定义菜单与关键词自动回复互斥解决
    转载《Spring AOP中pointcut expression表达式解析 及匹配多个条件》
    ssm 动态切换数据源
    spring aop
    微信公众号自动回复
    转载《spring定时任务轮询(spring Task)》
    N 秒打开一个新窗口
    java webservice maven spring Class Not Found Exception解决
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13466797.html
Copyright © 2020-2023  润新知