BF相当于一种暴力枚举,是手中没有地图的旅客
而KMP则会是手中有地图,看地图走的旅客
1. 效率分析
给定主串和模式串,分别统计模式匹配的BF算法和KMP算法的比较次数。
如主串为S=aaaaaaaaaa ,模式串为T=aaaab
BF比较次数为 34
KMP比较次数为 16
如主串为S=cdbbacc ,模式串为T=abcd
BF比较次数为 8
KMP比较次数为 8
KMP这个算法,理解了以后你会发现,都是脑子,为啥这么不同呢
🌚🌚🌚
2.BF代码
int BF(string A, string B)
{ int i =0, j = 0,count=0;
while (i < A.length() && j < B.length())
{ count++;
//两个字符串均为比较到串尾(只有有一个到串尾就跳出循环)
if (A[i] == B[j])
{ i++;
j++; }
else { //匹配失败指针回溯
i = i - j + 1;
j = 0; }
} return count;
/*if (j >= B.length()) return i - B.length();
else return count;*/
}
BF原理很简单,就是对主串的每一个字母为开头,与子串比较,如果相等,则匹配成功,而作为这个开头的就是上面代码中的i,作为子串开头的,就是这个j
i永不回溯,而j一但匹配失败,则回溯到子串首字母
KMP代码
int KMP(string str,string p)
{
int count = 0;
int k=-1,j=0,next[p.length()];
next[0]= -1;
while(j<p.length())
if(k==-1||p[j]==p[k])
next[++j] = ++k;
else k=next[k];
int q=0,e=0;
while(q<str.length()&&e<p.length())
{ count++;
if(q==-1||p[e]==str[q])
{
e++;
q++;
}
else
{
e=next[e];
}
}
return count;
}
KMP算法,总体可分为两步
而这两部最核心的自然就是找到地图,即next数组
next数组怎么找呢,代码如下
next数组代码
int k=-1,j=0,next[p.length()];
next[0]= -1;
while(j<p.length())如果未满
if(k==-1||p[j]==p[k])
next[++j] = ++k;
else k=next[k];
这个就相当于子串回溯后的位置
什么意思呢,上面不是说到BF算法是j回溯到子串头部,而这个就相当于看地图走的那条捷径,前提是有捷径了话,即在子串有最大前后缀数时,j不再用回溯到头部,而是根据这个next数组走。
而很多人看不懂这个k=next[k]
else k=next[k];
这里相当于递归,找到现在k个最大前后缀中的最大前后缀,如果一直没有,那么这个将会回到k=-1,即子串头部
以及
next[++j] = ++k;
这里的插入位置有必要说明
next[++j] = ++k; 计算的k永远是j上一位的最大前后缀数,而这里的k存到j位置。
这和匹配机制有关,即匹配失败时,看的应该是当前位置的上一级的相同前缀,匹配位置永远是后缀
所以找前缀
然后就是看地图去走
int q=0,e=0;
while(q<str.length()&&e<p.length())
{
if(q==-1||p[e]==str[q])
{ e++;
q++;
}
else
e=next[e];
}
}
if(q==-1||p[e]==str[q])
即当子串指针在头部或者与主串相等
e=next[e];
即看地图找路
是不是恍然大悟?😏
如果想看BF或者kmp是否匹配成功,只需要对他们的主串指针和子串指针操作就行啦
也就是看是主串遍历完(失败)还是子串遍历完(成功)
如果想计算次数,那么加一个计数器就好啦
int count=0;
主函数
int main(){
string str,p;
cin>>str>>p;
cout<<"BF:"<<BF(str,p)<<endl; cout<<"KMP:"<<KMP(str,p)<<endl;}
这里就是简单的调用
#include<bits×dc++.h>
using namespace std;
int BF(string A, string B) {
int i =0, j = 0,count=0;
while (i < A.length() && j < B.length()) {
count++;
//两个字符串均为比较到串尾(只有有一个到串尾就跳出循环)
if (A[i] == B[j]) {
i++;
j++;
}
else {
//匹配失败指针回溯
i = i - j + 1;
j = 0;
}
}
return count;
/*if (j >= B.length()) return i - B.length();
else return count;*/
}
int KMP(string str,string p)
{ int count = 0;
int k=-1,j=0,next[p.length()];
next[0]= -1;
while(j<p.length())
if(k==-1||p[j]==p[k])
next[++j] = ++k;
else k=next[k];
int q=0,e=0;
while(q<str.length()&&e<p.length())
{ count++;
if(q==-1||p[e]==str[q])
{
e++;
q++;
}
else
{
e=next[e];
}
}
return count;
}
int main()
{
string str,p;
cin>>str>>p;
cout<<"BF:"<<BF(str,p)<<endl;
cout<<"KMP:"<<KMP(str,p)<<endl;
}
有事请@王也枉不了
利用Fiddler实现在pc微信端测试 我们在一些工作中需要用到微信内置的浏览器但是...
文章目录 1.先决条件 1.1 支持平台 1.2 jdk及hadoop安装包 1.3 Xshell 7与Xftp 7...
相信许多人都有MSN聊天工具的帐号,例如abc@hotmail.com ,这个账号其实也是一个...
Quoted-printable 可译为“可打印字符引用编码”、“使用可打印字符的编码”,我...
本文实例讲述了laravel框架中表单请求类型和CSRF防护。分享给大家供大家参考,具...
一、HTML常用标签的优化 对于html,应该是网络编辑的基本技能,不熟悉是说不过的...
作为 2020年10月补丁安全更新的一部分,Microsoft为Windows添加了一个新选项,使...
在一个多用户的系统中,限制每个用户可以使用的最大存储容量显得非常重要。如果...
微软新的操作系统Windows 10X几乎已经准备好了,代号为Santorini,它基本上是为...
期待见到你~ ;原文链接:https://blog.csdn.net/jILRvRTrc/article/details/101...