数据结构:KMP 算法
BF 算法#
算法思想#
BF 算法,即暴风(Brute Force)算法,不是要匹配字符吗?那我一个一个直接匹配不就好啦。BF 算法的思想就是将目标串 S 的第一个字符与模式串 T 的第一个字符进行匹配,若相等,则继续比较 S 的第二个字符和 T 的第二个字符;若不相等,则比较S的第二个字符和 T 的第一个字符,依次比较下去,直到得出最后的匹配结果。
代码实现#
#include <string.h>
int BF(const char* str, const char* sub, int pos)//O(n*m)
{
int i = pos;
int j = 0;
while (i < strlen(str) && j < strlen(sub))
{
if (str[i] == sub[j]) //同时移动 i 和 j
{
i++;
j++;
}
else
{
i = i - j + 1; //i 退回到当前匹配失败的字符串第一个字符的下一个
j = 0; //j 回退到 0,即回溯
}
}
if (j >= strlen(sub)) //匹配
return i - j;
else //失配
return -1;
}
KMP 算法思想#
假设我们的目标串是 “abcdefgab……”,模式串是 “abcde&”,那么使用 BF 算法匹配流程如下所示。
但是在模式串中,第一个字符 “a” 与后面的字符 “bcde&” 都不一样,也就是说对于第一步,前 5 位字符都匹配成功了,那么 “a” 与目标串中的第 2~5 个字符一定不能匹配,那么流程就可以缩减成这样:
再看个例子,假设我们的目标串是 “abcababca……”,模式串是 “abcab&”,那么使用 BF 算法匹配流程如下所示。
因为模式串中的第一位和第四位的字符都是 “a”,第二位和第五位字符都是 “b”,而第四位和第五位在第一步的时候已经匹配成功了,因此匹配的过程可以简化为:
那么这种思想就是 KMP 算法,这种算法的思想是为了让不必要的回溯不发生。
KMP 算法是一种改进的字符串匹配算法,由 D.E.Knuth,J.H.Morris 和 V.R.Pratt 提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称 KMP 算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 next() 函数实现,函数本身包含了模式串的局部匹配信息。KMP 算法的时间复杂度 O(m+n)。
代码实现#
匹配函数#
int KMP(string str, string t, int pos)
{
int i = pos; //从字符串的 pos 下标开始匹配
int j = 0; //用于描述模式串 t 的下标
int next[t.size()];
getNext(t, next);
while (i <= str.size() && i <= t.size())
{
if (j == -1 || str[i] == t[j]) //两字符相等,继续判断
{
i++;
j++;
}
else //不相等,回溯
{
j = next[j];
}
}
if (j > t.size())
return i - t.size;
else
return -1;
}
求 next 数组#
void getNext(string t,int next[])
{
int i = 0,j = -1;
next[0] = -1;
while(i < t.size())
{
if(j == -1 || t[i] == t[j]) //匹配前缀和后缀
{
i++;
j++;
next[i] = j;
}
else
j = next[j]; //字符不相同,回溯
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)