字符串匹配_KMP算法_C语言


在这里插入图片描述

一、KMP是什么?

KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法
KMP分别取三个学者名字的首字母
KMP:当字符串出现不匹配的情况下,不再重复进行前一部分已经匹配成功的内容,避免从头匹配。

二、前缀表

前缀表是用来回退使用的,他记录了模式串和主串发生不匹配的时候,模式串应该从哪里开始重新匹配,应该回退几个。
前缀表:记录下标i之前(包括i)的字符串中,有多大长度的相同前后缀,即最大公共前后缀

前缀:指的是不包括最后一个字符的所有以第一个字符开头的连续子串
后缀:指的是不包括第一个字符的所有以最后一个字符结尾的连续子串
最长相等的前后缀的长度(最长公共前后缀):一个字符串中前后缀相等的最大长度
在这里插入图片描述前缀表
在这里插入图片描述

使用前缀表进行匹配的过程:
在这里插入图片描述开始匹配时,主串和模式串每个字符进行比对,比较完成后进行向后移动一位,进行比较,遇到冲突不匹配的位置,找模式串该位置前一位的子串的最长相等前后缀,这里的最长相等前后缀就记录在前缀表中,在以上例子中标红的2即为最长相等前后缀,意味着这里的后缀aa前面也有一个与之相等的aa。跳到前缀的后面的一个字符,前缀的后一个字符的下标即为前缀的长度(因为索引从0开始),模式串跳转到前缀后面的一个字符后,继续向后移动匹配,不在进行前面匹配成功字符串匹配。

三、prefix和next数组

prefix存放前缀表 ,next有时会对前缀表进行调整,两者都可以
next数组有些进行右移一位 然后起始位置 “-1”
有些进行将前缀表进行统一减1。
有些也可以直接使用前缀表也可以完成KMP算法。
只是对KMP的不同的实现,不必太过于纠结。

四、代码部分

#include<stdio.h>
#include<string.h>

void get_next(char *T, int next[]) {
    int strs_len = strlen(T);
    int i = 0, j = -1;
    next[0]=-1;
    while (i < strs_len) {  //遍历
        if (j == -1 || T[i] == T[j]) {
            i++;
            j++;
            next[i] = j;
        } else {
            j=next[j];
        }
    }
}

int kmp(char *str_main,char * str_branch){
    int next[100];
    int str_main_len = strlen(str_main);
    int str_branch_len = strlen(str_branch);
    int i,j;
    get_next(str_branch,next);
    i=0;
    j=0;
    /*kmp 核心
        当主串i和子串j相等的时候,i++,j++;
        反之 j = next[j];
        当 j==-1 的时候,i++,j++
    */
    while ( i < str_main_len && j < str_branch_len )
    {
        if(str_main[i]==str_branch[j]){
            i++;
            j++;
        }else{
            j = next[j];
            if(j==-1){
                j++;
                i++;
            }
        }
    }
    if(j>=str_branch_len){
        /*此时说明在主串中找到了子串*/
        return i-str_branch_len;
    }else{
        return -1;//没有找到的话返回-1
    }

}

int main() {
    char str1[100] = "aabaabaaf";
    char str2[100]= "aabaaf";
    if(kmp(str1,str2) != -1){
        printf("子串在主串中开头位置为:%d\n",kmp(str1,str2));
    }else
    {
        printf("没有在主串中找到该子串");
    }
    return 0;
}


执行结果:
在这里插入图片描述

注:学习笔记,如有错误,还请指正。
感谢各位阅读。

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
KMP算法是一种字符串匹配算法,可以在O(n+m)的时间复杂度内,判断一个字符串是否是另一个字符串的子串。 KMP算法的核心思想是利用已知信息来避免无用的匹配。在匹配过程中,如果某个字符不匹配,那么就说明已经匹配的部分中可能存在一些前缀或后缀与模式串相同,此时可以利用这些已知信息,避免重复匹配。具体来说,KMP算法会预处理模式串,得到一个next数组,其中next[i]表示模式串中以i结尾的子串中最长的既是前缀又是后缀的字符串的长度。在匹配过程中,当发现某个字符不匹配时,就可以根据next数组跳过一些无用的匹配。 下面是C语言实现KMP算法的代码: ```c #include <stdio.h> #include <string.h> void getNext(char *p, int *next) { int i = 0, j = -1; next[0] = -1; while (p[i] != '\0') { if (j == -1 || p[i] == p[j]) { i++; j++; next[i] = j; } else { j = next[j]; } } } int kmp(char *s, char *p) { int i = 0, j = 0; int slen = strlen(s); int plen = strlen(p); int next[plen]; getNext(p, next); while (i < slen && j < plen) { if (j == -1 || s[i] == p[j]) { i++; j++; } else { j = next[j]; } } if (j == plen) { return i - j; } else { return -1; } } int main() { char s[] = "ababababc"; char p[] = "abc"; int pos = kmp(s, p); printf("%d\n", pos); return 0; } ``` 其中getNext函数用于计算next数组,kmp函数用于执行匹配。在实际使用中,可以将KMP算法封装成一个函数,方便调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值