KMP算法

好久没写博客了,最近在学数据结构,今天来分享一下字符串的匹配算法。

朴素的模式匹配算法

这个方法比较容易理解(简称:暴力匹配),大概思路是这样的:从S的第一个字符S0开始,将P中的字符依次和S中字符比较,若S0=P0 && …… && Sm-1 = Pm-1,则证明匹配成功,剩下的匹配无需进行了,返回下标0。若在某一步Si != Pi 则P中剩下的字符也不用比较了,不可能匹配成功了,然后从S中第二个字符开始与P中第一个字符进行比较,同理,也是知道Sm = Pm-1或者找到某个i使得Si != S-1为止。依次类推若知道以S中第n-m个开始字符为止,还没有匹配成功则证明S中不存模式P。

void pattern_match(seqstring* p, seqstring* t)//寻找模式p在t中的位置
{
    int i, j, succ;
    i = 0; succ = 0;
    while ((i <= t->length - p->length) && !succ)
    {
        j = 0; succ = 1;
        while ((j < p->length) && succ)
        {
            if (p->str[j] == t->str[i + j])j++;
            else succ = 0;
        }
        ++i;
    }
    if (succ)printf("nice! 与原字符串 %d-%d 字符串成功匹配。\n",i,i+t->length-1);
    else printf("匹配失败\n");
}

快速模式匹配算法(KMP)

上面的算法易理解,但代码效率不高。KMP算法关键在于如何求得next值。作一个对比,朴素的模式匹配算法是:从主串第i个位置开始与模型字符窜p匹配,若匹配失败,则返回来再从第i+1个位置开始检索匹配,直至结束。也就是说(i+1)-i=1 ,主串每次移动的只是一个元素,但这样效率低下,所以有的元素处 他就可以一下子移动好几个位置,从而我们的好几个位置就等于next[i]。
废话少说,直接上代码

 int i, j = 0, next[20]; next[0] = 0;
    for (i = 1; i < p->length; ++i)
    {
        while (j > 0 && p->str[i] != t->str[j])j = next[j - 1];
        if (p->str[i] == p->str[j])j++;
            next[i] = j;
    }

求next主要分为四步:
1、初始化

 int i, j = 0, next[20]; next[0] = 0;

2、前后缀不相同

while (j > 0 && p->str[i] != t->str[j])j = next[j - 1];

3、前后缀相同

if (p->str[i] == p->str[j])j++;

4、求next

 next[i] = j;

接着就比较简单了,利用next值进行匹配求值。

i = 0; j = 0;
    while (i < t->length && j < p->length)
    {
        if (j==0||t->str[i] == p->str[j])
        {
            i++; j++;
        }
        else j = next[j - 1];
    }

KMP源码如下:

void KMP_match(seqstring* t, seqstring* p)
{
    
    int i, j = 0, next[20]; next[0] = 0;
    for (i = 1; i < p->length; ++i)
    {
        while (j > 0 && p->str[i] != t->str[j])j = next[j - 1];
        if (p->str[i] == p->str[j])j++;
            next[i] = j;
    }//求next
    i = 0; j = 0;
    while (i < t->length && j < p->length)
    {
        if (j==0||t->str[i] == p->str[j])
        {
            i++; j++;
        }
        else j = next[j - 1];
    }
    if (j == p->length)printf("匹配成功:%d-%d \n", i - p->length + 1, i);
    else printf("匹配失败!\n");
}

最后如果大家还有不懂的话,附赠视频希望可以帮到你哦!
https://www.bilibili.com/video/BV1M5411j7Xx
https://www.bilibili.com/video/BV1tW41157tv/?spm_id_from=333.788.videocard.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值