字符串匹配算法KMP算法

简介:

数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法。

朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较。假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法。

KMP算法:

kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(abaabcac),那么从字串abaabcac下手,分析字串时,需要借助于一个数组存储字串中存在头字串和尾字串对称相等的子串长度,例如 abaabcac,

a  next[0] = -1,规定第一个字符对应的next值为-1;

ab next[1] = 0; 因为针对字符b而言,其前边字符串a 不存在头字串和尾字串对称,所以为0;

aba next[2]=0 ; 因为针对子串 ab ,不存在头字串和尾字串对称,所以为0;

abaa next[3]=1 ; 因为针对子串aba ,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;

abaab next[4]=1; 因为针对子串abaa ,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;

abaabc next[5]=2; 因为针对子串abaab ,存在 头子串ab和尾子串ab对称相等,其长度为2,所以为2;

abaabca next[5]=0; 因为针对子串abaab ,,不存在头字串和尾字串对称,所以为0;

abaabcac next[6]=1; 因为针对子串abaabca,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;

 总结起来如下:

  

J            0    1    2    3    4    5    6    7
P            a    b    a    a    b    c    a    c
next(j)      -1    0    0    1    1    2    0    1

获取next数组的代码如下

复制代码
//获取模式匹配字符串的next数组
void getNext(char *str,char *next)
{
    int j = 0;
    int k = -1;
    int length = strlen(str);
    next[0] = -1;
    while(j<length)
    {
        if(k == -1 || str[j] == str[k])
        {
            j++;
            k++;
            next[j] = k;
        }else k = next[k];
    }
}
复制代码

然后在匹配的过程中,如果遇到不匹配现象时,从不匹配位置分析,其next[i]的值标记着有n个头子串和尾子串相等,即直接从next[i]的值为下标开始寻找匹配。复杂度为O(m+n)   KMP实现代码:

复制代码
//src为要匹配的字符串,pat为字符串模型
int KMP(char *src,char *pat)
{
    char next[100];
    getNext(pat,next);
    int lengthP = strlen(pat);
    int lengthS = strlen(src);
    int posS=0,posP=-1;
    bool flag = false;
    while(posS < lengthS && posP < lengthP)
    {
        if (posP==-1 ||src[posS] == pat[posP])
        {
            if (flag)
            posS++;
            posP++;
        }else
        {
            posP = next[posP];
            flag = true;
        }
    }
    if (posP<lengthP)return -1;
    else return posS-lengthP;
}
复制代码

 

完整的代码:

 

复制代码
#include<stdio.h>
#include<string.h>

//获取模式匹配字符串的next数组
void getNext(char *str,char *next)
{
    int j = 0;
    int k = -1;
    int length = strlen(str);
    next[0] = -1;
    while(j<length)
    {
        if(k == -1 || str[j] == str[k])
        {
            j++;
            k++;
            next[j] = k;
        }else k = next[k];
    }
}

//src为要匹配的字符串,pat为字符串模型
int KMP(char *src,char *pat)
{
    char next[100];
    getNext(pat,next);
    int lengthP = strlen(pat);
    int lengthS = strlen(src);
    int posS=0,posP=-1;
    bool flag = false;
    while(posS < lengthS && posP < lengthP)
    {
        if (posP==-1 ||src[posS] == pat[posP])
        {
            if (flag)
            posS++;
            posP++;
        }else
        {
            posP = next[posP];
            flag = true;
        }
    }
    if (posP<lengthP)return -1;
    else return posS-lengthP;
}
int main()
{
    char src[100];
    char pat[50];
    printf("请输入要匹配的字符串和字符串模板(字串):\n");
    scanf("%s%s",src,pat);
    int f = KMP(src,pat);
    printf("在元字符串中匹配位置的下标为 %d ",f);
    return 0;
}
复制代码

 









本文转自NewPanderKing51CTO博客,原文链接:http://www.cnblogs.com/newpanderking/p/3879121.html ,如需转载请自行联系原作者

相关文章
|
1月前
|
算法
【优选算法】—— 字符串匹配算法
【优选算法】—— 字符串匹配算法
|
2月前
|
人工智能 算法 测试技术
【动态规划】【字符串】【C++算法】940. 不同的子序列 II
【动态规划】【字符串】【C++算法】940. 不同的子序列 II
|
2月前
|
机器学习/深度学习 算法 C语言
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
73 0
|
1月前
|
算法 Java
[Java·算法·简单] LeetCode 28. 找出字符串中第一个匹配项的下标 详细解读
[Java·算法·简单] LeetCode 28. 找出字符串中第一个匹配项的下标 详细解读
21 0
|
1月前
|
算法
白话 KMP 算法
白话 KMP 算法
12 2
|
1月前
|
算法 Java 索引
算法基础:KMP算法详细详解
算法基础:KMP算法详细详解
|
2月前
|
算法 测试技术 C++
【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串
【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串
|
2月前
|
算法 测试技术 C++
【KMP】【二分查找】【C++算法】100207. 找出数组中的美丽下标 II
【KMP】【二分查找】【C++算法】100207. 找出数组中的美丽下标 II
|
2月前
|
算法
KMP 算法小结
KMP 算法小结
10 0
|
2月前
|
算法 搜索推荐 程序员
C语言第三十三练—— KMP算法和扩展 KMP算法
C语言第三十三练—— KMP算法和扩展 KMP算法
33 0