【模板算法】字符串匹配问题——MP算法+KMP算法

MP算法介绍:

字符串匹配中,如果我们选择最朴素的BF算法,即每次匹配失败就返回到该次刚开始匹配的位置,时间复杂度为O(M*N),M,N分别为匹配字符串p和被匹配字符串s的长度。这个复杂度在M和N长度都很大时是极其不方便的,所以,我们需要想办法利用现有的资料去减少匹配次数。如果我们在p[i]处匹配失败了,可以知道的是前0-i-1是匹配成功的,那么我们可以根据这个将P向后滑动,而不是将P移到最前面。

MP算法实现原理

现在我们需要知道的是向后滑动几个字符。我们怎么判断向后滑动的字符数呢?当然是滑动到其当前后缀与前缀相同的最大位置,例如abcabcc为匹配字符串,如果在第6位时失配了,那我们可以知道的是前5位是相同的,那么ab这个后缀与前缀ab是相同的,我们就可以把字符串滑动到第三位继续比较,从而节省了大量的时间。

预处理mpNext数组

void preMp(char s[]){
    int length=strlen(s),i=0,j=-1;
    mpNext[0]=-1;
    while(i<length){
        while(j>-1&&s[i]!=s[j])j=mpNext[j];
        mpNext[++i]=++j;
    }
    for(i=0;i<=length;i++){
        printf("%d ",mpNext[i]);
    }
    printf("\n");
}

KMP算法实现原理

KMP是在MP算法的基础上改进出来的,核心思想为避免MP算法中一次明显失败的匹配。
例如abcabcc为匹配字符串,如果在第6位时失配了,那我们可以知道的是前5位是相同的,那么ab这个后缀与前缀ab是相同的,MP算法会将字符串移动到第3位,但是第3位也是c,而第6位的字符可以确定不是c,所以就在代码中添加条件,如果mpNext数组第i位匹配的位置j的字符a和第i位字符相同,则kmpNext数组中会赋值为kmpNext[j],而不是j。

预处理KMP数组

void preKMp(char s[]){
    int length=strlen(s),i=0,j=-1;
    KmpNext[0]=-1;
    while(i<length){
        while(j>-1&&s[i]!=s[j])j=KmpNext[j];
        ++i;
        ++j;
        if(s[i]==s[j])KmpNext[i]=kmpNext[j];
        else KmpNext[i]=j;
    }
    for(i=0;i<=length;i++){
        printf("%d ",mpNext[i]);
    }
    printf("\n");
}

MP算法测试代码

KMP就是将其替换为上面的方法即可,注意数组名。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int mpNext[100];
void preMp(char s[]){//预处理mpNext数组 
    int length=strlen(s),i=0,j=-1;
    mpNext[0]=-1;
    while(i<length){
        while(j>-1&&s[i]!=s[j])j=mpNext[j];
        mpNext[++i]=++j;
    }
    printf("预处理mpNext数组:\n");
    for(i=0;i<=length;i++){
        printf("%d ",mpNext[i]);
    }
    printf("\n");
}
int main() {
    char S[]="catcatcaatcatcatcaatcatacaat";
    char P[]="catcaat"; 
    printf("被匹配字符串:\n%s\n",S);
    printf("匹配字符串:\n%s\n",P);

    preMp(P);//预处理mpNext数组 

    int i=0,j=0,sl=strlen(S),pl=strlen(P);
    while(i<sl){
        while(j>-1&&P[j]!=S[i])j=mpNext[j];
        i++;j++;
        if(j>=pl){
            printf("Matching at: %d\n",i-j+1);
            j=mpNext[j];
        }           
    }
    return 0; 
}
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/tjj1998/article/details/79903289
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞