文章目录
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 <

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

被折叠的 条评论
为什么被折叠?



