C语言:KMP模式匹配

KMP模式匹配:

时间复杂度O(n+m)
意义:已匹配的指针i不用回退了

概念解释

主串标记i,模式串标记j
前缀:除最后一个字符外,字符串的所有头部子串;
后缀:除最后一个字符外,字符串的所有尾部子串;
部分匹配值:字符串前缀和后缀最长相等前后缀长度。

在这里插入图片描述

下次移动位数:已匹配部分数据段长度-部分匹配值
先统计已匹配i个模式串字符时,该i个模式串字符的部分匹配值next[j]
下次移动位数=(j-1)-next[j-1]
移到j发现不匹配了,所以已匹配长度=j-1,若用原始算法,i应退回(i-j+1)+1的位置

部分匹配数组定义

匹配到第j个不相同时,下次开始匹配模式串的位置

void GetNext(char c[], int *next){
    int i=1, j=0, n;    //j:模式串中头尾相匹配的个数
    next[0]=0;  
    n = strlen(c);
    while(i < n){
        if( j==0 && c[i]!=c[j] ) {  //匹配到第二个元素不一样,下次从next[0]开始
            next[i]=0; ++i;
        }
        else if( c[i]==c[j] ){  //头尾相匹配,++j,next[i]=j,++i
            j++; next[i]=j; i++;
        }
        else{   //从非第一个位置开始,若不匹配从next[j-1]个重新匹配
            j=next[j-1];
        }
    }
}

KMP匹配过程

int KMPmatch(char original[],char module[]){
    int orlen,molen,i=0,j=0;      
    int next[100];  //匹配到第j个不一样,下次从第next[j]的位置匹配,模式串最长100
    GetNext(module,next);   //为模式串各个匹配长度的部分匹配长度赋值
    orlen = strlen(original); molen = strlen(module);
    while(i<orlen && j<molen){
        if(j==0 && original[i]!=module[j]){ //第一个数字就不一样
            ++i;
        }
        else if( original[i]==module[j] ){  //匹配相等
            ++i;  ++j;
        }
        else{   //j!=0且匹配不相等,j后退部分匹配个数
            j=next[j];
        }
    }
    if(j==molen) return i-j+1;   //匹配成功,返回变量所在位置
    else if(i==orlen) return NOTHAVE;
    else return -9999;
}

文件初始定义

#include <stdio.h>
#include <stdlib.h>

#define NOTHAVE 0
int strlen(char *c){
    int i=0;
    while(c[i] != '\0'){   //字符串以'\0'结尾
        i++;
    }
    return i;
}

main函数测试

int main(){
    char origin[50],modu[10]; int next[50]; int i,n;
    scanf("%s",origin);
    scanf(" %s",modu);
    GetNext(modu, next);
    n = strlen(modu);
//    for (i=0; i<n; i++){
//        printf("%d,",next[i]);
//    }
    int num = 0;
    num = KMPmatch(origin, modu);
    printf("\n%d",num);         //输出匹配到的位置
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值