数据结构学习之字符串匹配算法(BF||KMP)

0x1 实验目的

​ 通过实验深入了解字符串常用的匹配算法(BF暴力匹配、KMP、优化KMP算法)思想。

0x2 实验要求

​ 编写出BF暴力匹配、KMP、优化KMP的代码模型

0x2 代码

0x2.1.1 BF暴力匹配

#include <iostream>
#include <string> using namespace std;
int BF1(string s1,string s2)
{
int len=s2.length();
for(int i=0;i<s1.length();i++)
{
int n=len;
int j=i;
while(n)
{
//cout<< s1[j] <<endl;
if(s1[j++] != s2[len-n])
break;
n--;
}
if(n==0)
return i+1;
}
return -1;
} int BF2(string s1,string s2)
{
int i=0;
int j=0;
while(i<s1.length() && j<s2.length())
{
if(s1[i]==s2[j])
{
i++;
j++;
}else
{
i=i-j+1;
j=0;
}
}
if(j>=s2.length())
return (i-j+1);
else
return -1;
} int main()
{
string s1="asfasgasgsd";
string s2="asg";
cout<< BF1(s1,s2) <<endl;
cout<< BF2(s1,s2) <<endl;
return 0;
}

0x2.1.2 结果

0x2.1.3 体会

​ 我写了两种,一开始我没看书自己意淫了第一种出来,代码不够书本简洁,本着向优秀代码学习的精神,还有对应对应下面KMP的匹配过程,第二种写法更有益于学习。过程主要是,while(i<s.length() && j<t.length())来判断退出,其中跟kmp不同的是,i需要i-j+1,j=0回溯,该算法的时间复杂度0(n*m)。

0x2.2 KMP || KMP优化

#include <iostream>
#include <string>
#define maxsize 200+7
using namespace std;
int next[maxsize];
int nextval[maxsize]; void GetNext(string s,int next[])
{
int j=0,k=-1;
next[0]=-1;
while(j<s.length()-1) //因为数组下标最大是s1.length()-1,下面是j++故j可以到达最大值
{
if(k==-1 || s[j]==s[k])
{
j++,k++;
next[j]=k;
}else
{
k=next[k];
}
}
} void GetNextVal(string s,int nextval[])
{
int j=0,k=-1;
nextval[0]=-1;
while(j<s.length()-1)
{
if(k==-1 || s[j]==s[k])
{
j++,k++;
if(s[j]!=s[k])
nextval[j]=k;
else
nextval[j]=nextval[k];
}else
{
k=nextval[k];
}
}
} //KMP优化
int KMPIndex1(string s,string t)
{
int i=0,j=0;
int next[maxsize];
GetNext(t,next);
while(i<s.length() && j<t.length())
{
if(j==-1 || s[i]==t[j])
{
i++,j++;
}else
{
j=next[j];
}
}
if(j>=t.length())
return(i-t.length());
else
return -1; }
//KMP优化
int KMPIndex2(string s,string t)
{
int i=0,j=0;
int nextval[maxsize];
GetNextVal(t,nextval);
while(i<s.length() && j<t.length())
{
if(j==-1 || s[i]==t[j])
{
i++,j++;
}else
{
j=nextval[j];
}
}
if(j>=t.length())
return(i-t.length());
else
return -1; }
int main()
{
string s="aaaaab";
string t="aaab";
cout<< KMPIndex1(s,t) <<endl;
cout<< KMPIndex2(s,t) <<endl;
return 0;
}

0x2.2.1 结果

0x2.2.2 体会

​ kmp算法主要思想是利用模式串自身的特点,避免主串的回溯过程,同时通过next数组,也减少了模式串的回溯长度。

首先是定义:

\[next[j]=\left\{\begin{matrix}-1 \qquad 当j=0时
\\MAX \left \{ k|0<k<j\ 且 \ t_{0}t_{1}\cdots t_{k-1} = t_{j-k}t_{j-k+1}\cdots t_{j-1}\right \} \ 当此集合非空时
\\ 0 \qquad 其他情况
\end{matrix}\right.
\]

主要思想是:

​ 比如一个模式串 ababb 显然前4个字符串满足 ab=ab 也就是$$t_{0}t_{1}=t_{2}t_{3}$$ 当你去用模式串去匹配串ababaababb的时候可以发现$$t_{4} \neq s_{4}$$,这个时候就直接可以跳转到 $$s_{2}$$ 开始 而不是从$$s_{1}$$开始,关于这个证明其实也很简单,如下:

​ aba $$\neq$$ bab 然后你发现这里了没有,从$$s_{1}$$开始其实就是从bab开始很明显就是不等,其实kmp就是这种规律,找出最大长度的前后缀,那么就确定了这个模式串滑动的长度,说的更简单点就是模式串包含了主串的信息,模式串跟主串的比较就可以转换为模式串跟自己的比较,就像上面的例子,通过反证法可以得到移动<next[j]的话必定会不想等。

代码重点是:

//初始化
next[0]=-1;
int j=0,k=-1;
while(j<s.length()-1)
{
if(k==-1 || s[j]==s[k])
{
j++,k++;
next[j]=k; //重点
}else
{
k=next[k]; //重点 abdbabc 显然c -> ab开头的两个字符,d不等于c,那么只能从a=c这里去比较了next[2]=0
} }

0x3 最近学习总结

最近感觉自己特别浪,要学的东西还有很多,平时效率也好低,数据结构的作业也拖了好久,以前都是4天一次,这次竟然拖了那么10多天,最近要抓紧空闲时间去补回来了,下篇写一些递归的题目,介绍一些好玩的知识点。

数据结构学习之字符串匹配算法(BF||KMP)的更多相关文章

  1. 字符串匹配算法之 kmp算法 (python版)

    字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...

  2. Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化

    1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...

  3. 字符串匹配算法之————KMP算法

    上一篇中讲到暴力法字符串匹配算法,但是暴力法明显存在这样一个问题:一次只移动一个字符.但实际上,针对不同的匹配情况,每次移动的间隔可以更大,没有必要每次只是移动一位: 关于KMP算法的描述,推荐一篇博 ...

  4. 字符串匹配算法之kmp算法

    kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法 算法思想 在一个字符串中查找另一个字符串时,会遇到如下图的情况 我们通常 ...

  5. 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!

    前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...

  6. 字符串匹配算法(三)-KMP算法

    今天我们来聊一下字符串匹配算法里最著名的算法-KMP算法,KMP算法的全称是 Knuth Morris Pratt 算法,是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Prat ...

  7. 字符串KMP——用途广泛的字符串匹配算法 + 扩展KMP——特殊定义的字符串匹配

    引 入 引入 引入 " SY 和 WYX 在看毛片.(几 毛 钱买到的动作 片,毛 片) WYX 突然想回味一个片段,但是只记得台词里面有一句挺长的 " ∗ ∗ ∗ ∗ **** ...

  8. 字符串匹配算法——BF、KMP、Sunday

    一:Brute force 从源串的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到源串的第二个字符,重复上述步骤,直到整个模式串在源串中找到匹 ...

  9. 字符串匹配算法BF和KMP总结

    背景 来看一道leetcode题目: Implement strStr(). Returns the index of the first occurrence of needle in haysta ...

随机推荐

  1. MongoDB安装与使用体验

    1.获取并安装 具体的安装包可以到官方网站下载:http://www.mongodb.org/downloads 我看着教程就下载了linux版本吧,也不是很复杂.包的体积有点大. 安装过程比较简单, ...

  2. Python算法和数据结构:在二叉树中找到和为sum的所有路径

    玄魂工作室秘书 [玄魂工作室] 思路:先用递归创建一颗二叉树,作为输入:然后对这课二查树进行递归遍历,递归中每遍历一个节点,下次递归的和为sum-data;并用一个数组记录遍历过的路径,当存在sum时 ...

  3. Objective-C 学习 (二):Objective-C 实战之Hello World

    在Objective-C 学习 (一):Objective-C 概述 学习了OC的基本知识,本节我们来实战一下: #import <Foundation/Foundation.h> // ...

  4. 仓储repository概念

    1.为什么要用仓储?(仓储有什么用) 1.1 解耦 为了解耦领域层与数据映射层的关系. 1.2 管理增删查改 仓储模式最大的优点就是所有的数据访问首先是通过仓库的,对仓库的增删改都不会立即提交到数据库 ...

  5. 【Caffe篇】--Caffe从入门到初始及各层介绍

    一.前述 Caffe,全称Convolutional Architecture for Fast Feature Embedding.是一种常用的深度学习框架,主要应用在视频.图像处理方面的应用上.c ...

  6. Django rest framework源码分析(2)----权限

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  7. 一次生产 CPU 100% 排查优化实践

    前言 到了年底果然都不太平,最近又收到了运维报警:表示有些服务器负载非常高,让我们定位问题. 还真是想什么来什么,前些天还故意把某些服务器的负载提高(没错,老板让我写个 BUG!),不过还好是不同的环 ...

  8. ASP.Net Mvc实现自定义User Identity用户身份识别系统(2)

    上一篇博文中已经实现了如何在页面上使用自定义的属性即上篇博文所示的@this.U,今天将进一步研究用户自定义User Identity; 实现思路: 通过研究微软自带identity的套路,我们可以发 ...

  9. 关于Exceptionless的使用注意

    大家都应该比较熟悉NLOG,我们知道log4net和nlog,也有其它的记日志框架.目前我们的生产环境使用nlog,而且对Exceptionless的对接也是无缝的.可能有人会问为什么不用ELK,主要 ...

  10. Activiti(一) activiti数据库表说明

    activiti介绍: activiti是一个业务流程管理(BPM)框架.它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可执行流程语言框架.开发人员可以通过插件直接绘画出 ...