【算法竞赛】【模式串匹配算法(KMP)】【附带模板题】

本文详细介绍了KMP算法,包括算法原理、next数组的求解以及如何应用于字符串匹配。并提供了样例代码解析,展示如何使用KMP算法解决实际问题。同时,讲解了无线传输问题,通过next数组求解字符串的最长公共前后缀。

KMP

模式串匹配算法

开门见山,先看算法:

kmp算法:

inline void KMP(char *s1,char *s2,int len1,int len2){
   
    // KMP
	//s1 主串  ,len1 为 s1 长度 
	//s2 模式串,len2 为 s2 长度
    int i = 0, j = 0; //从0位开始匹配
    while (i < len1) {
   
     //临界值
        if (j == -1 || s1[i] == s2[j]) //匹配成功,继续
            i++, j++;
        else
            j = next_[j]; //失配
        if (j == len2)
            printf("%d\n", i - len2 + 1), j = next_[j];
        // j==len2时,匹配成功;i-len2+1即为第一个字母的位置;匹配成功后,j置为next_[j]
    }                                                      
}

BBC ABCDAB ABCDABCDABDE主串

ABCDABD模式串

下面初步说明匹配形式:
请添加图片描述

通过图像我们不难发现,每次当模式串有一部分已经匹配的时候:
在这里插入图片描述
如果下一个位置不匹配,则模式串的位置并不一定像朴素算法只向后移动一个位置,而是移动到模式串最长前后缀匹配的位置(next[j]):
在这里插入图片描述

给大家个例子:

字符串 abcdab
前缀的集合:{a,ab,abc,abcd,abcda}
后缀的集合:{b,ab,dab,cdab,bcdab}
那么最长相等前后缀就是 ab

模式串中每一个字符前的字符串都有最长相等前后缀(可能为0),而且最长相等前后缀的长度是我们移位的关键,所以我们单独用一个next数组存储子串的最长相等前后缀的长度。而且next数组的数值只与模式串本身有关

所以next[i]=j,含义是:下标为i 的字符前的字符串最长相等前后缀的长度为j

next[] 的求解算法:

inline void get_next(char *s2,int len2){
   
    //传入模式串及其长度,求出next_数组
    // next_数组是从 S[0到i-1]前子串 的前缀后缀最大值
    int i = 0, j;
    next_[0] = j = -1;
    while (i < len2)
        if (j == -1 || s2[i] == s2[j]) //类似于KMP的匹配
            next_[++i] = ++j;
        else
            j = next_[j]; //失配
}

看了这些还不过瘾,那让我们来做一道模板题吧:

【模板】KMP字符串匹配

题目描述

给出两个字符串 s 1 s_1 s1 s 2 s_2 s2,若 s 1 s_1 s1 的区间 [ l , r ] [l, r] [l,r] 子串与 s 2 s_2 s2 完全相同,则称 s 2 s_2 s2 s 1 s_1 s1 中出现了,其出现位置为 l l l
现在请你求出 s 2 s_2 <

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eternity_GQM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值