KMP算法的实现详解

简介: KMP算法的实现详解

@TOC


1.KMP算法

1.概念

KMP是一种改进的字符串匹配算法,该算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。 具体实现通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。

2.与BF(暴力算法)的的区别

暴力算法:模拟实现strstr函数

当信息匹配失败时,主串i不会回退,子串j也不会回到0号位置

  在这里插入图片描述  

3.分析

1.j的回退位置

在这里插入图片描述

>

在下标为5时,信息匹配失败,此时i不回退,在此匹配失败,说明 主串i与子串j下标5之前一定有一部分是相同的,此时j回退到 下标为2的位置,继续向后就能匹配成功。

2.next数组

next[j]=k来表示,不同的 j 对应一个k值,k为要移动的 j 要移动的位置

寻找k规则:

1.匹配成功部分的两个相等的真子串(不包含本身),一个以下标0开始,另一个以j-1下标开始结尾。

2.规定 next[0]=-1 ,next[1]=0, 正式计算是从下标2开始。

3.next数组的练习

1.练习1

在这里插入图片描述

在这里插入图片描述

注意事项

在这里插入图片描述

2.练习2

在这里插入图片描述 在这里插入图片描述  
注意事项
  在这里插入图片描述  

一个小细节:一般来说next数组下标 只会一个一个数加 或者被赋值成0

4.推导过程

在next[i]=k的前提下

在这里插入图片描述  

1.p[i]==p[k]

在p[0]……p[k-1] p[i-k]==p[i-1] ,   next[i]=k的前提下

….p[0]……p[k-1] p[k] == p[x]…p[i-1] p[i]   ,   next[i+1]=k+1

2.p[i]!=p[k]

在这里插入图片描述回退到下标为2的位置,发现此时p[i]!=p[k],则从当前位置继续回退,直到p[i]==p[k],再通过next[i+1]=p[k+1], 确定p[i+1]对应的next下标数

4.代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
//str代表主串
//sub代表子串
//pos代表从当前位置
void getnext(char* sub,int*next,int lensub)
{
    next[0] = -1;
    next[1] = 0;
    int i = 2;//下一项
    int k = 0;//前一项的k
    while (i < lensub)
    {
        if (k==-1||sub[i - 1] == sub[k])//当k==-1时,说明第一个数不符合条件,进入循环后next[i]会被置成0
        {
            next[i] = k + 1;
            i++;
            k++;
        }
        else
        {
            k = next[k];
        }
    }
}
int KMP(char* str, char* sub, int pos)
{
    assert(str != NULL && sub != NULL);
    int i = pos;
    int j = 0;
    int lenstr = strlen(str);//主串长度
    int lensub = strlen(sub);//子串长度
    int* next = (int*)malloc(sizeof(int) * lensub);
    assert(next != NULL);
    getnext(sub,next, lensub);
    while (i < lenstr && j < lensub)
    {
        if (j==-1||str[i] == sub[j])//当一个数不符合条件时,此时就需要加入一个条件,否则就会造成越界
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];
        }
    }
    if (j >= lensub)
    {
        return i - j;
    }
    return -1;
}
int main()
{
    char s1[40];
    char s2[40];
    scanf("%s%s", s1, s2);
    printf("%d\n", KMP(s1,s2,0));
    return 0;
}

1.代码的注意事项

1.next数组值为-1时
在这里插入图片描述 在这里插入图片描述  

当此时的p[i]!=p[k]时,一直通过next数组值返回到前面的p所在,但到第一个数依旧p[i]!=p[k]时,

则会将k置成-1,进入if循环后 k值为0 即 此位置的next所在下标为0

2.k值为-1时
在这里插入图片描述   在这里插入图片描述  

只有第一个数对应next数组的值为-1,说明主串与子串第一个数就信息匹配失败

而在if循环中如果不加入j==-1的判断 ,只有 sub[i]==sub[j],则会造成越界

2.KMP算法的优化

关于next数组的优化

在这里插入图片描述若在下标为5的位置信息匹配失败,就会 一直回退,直到下标为0的位置 优化的目的就会使 此时 直接找到下标为0的位置

1.规则

如果回退到的位置和当前字符一样,就写回退那个位置的nextval值

如果回退到位置和当前字符不一样,就写当前字符原来的nextval值

2.练习题

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
目录
相关文章
|
5月前
|
算法
数据结构中的KMP算法及其改进算法
KMP算法通过引入部分匹配表,有效避免了重复计算,从而将字符串匹配的时间复杂度降低到O(m+n)。通过进一步优化next数组,KMP算法的效率得到了进一步提升。对于大规模字符串匹配问题,KMP算法及其改进算法提供了高效的解决方案,是计算机科学领域的经典算法之一。
85 3
|
1月前
|
算法
第四章 KMP算法理论基础
第四章 KMP算法理论基础
19 0
|
1月前
|
算法
KMP算法
KMP算法
30 0
|
3月前
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
4月前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
119 1
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
3月前
|
算法
KMP算法
KMP算法
27 0
|
4月前
|
算法 Java
KMP算法详解及其在字符串匹配中的应用
KMP算法详解及其在字符串匹配中的应用
|
5月前
|
人工智能 算法 BI
一篇文章讲明白KMP算法(俗称看毛片算法)
一篇文章讲明白KMP算法(俗称看毛片算法)
57 0
|
5月前
|
算法 Java
Java数据结构与算法:字符串匹配算法之KMP算法
Java数据结构与算法:字符串匹配算法之KMP算法
|
6月前
|
算法