数据结构学习之字符串匹配算法(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. Android org.json.JSONArray cannot be converted to JSONObject

    今天在做Android项目移植的时候总是出现org.json.JSONArray cannot be converted to JSONObject异常,本着资源共享的理念,将异常处理过程以及引发该异 ...

  2. 使用maven生成可执行jar包(包含依赖)

    零零散散找了一些文章,有些感觉好乱,自己整理一下 以下是pom.xml里的配置,本来有很多依赖包,为了不让配置看着很长,我删了一些dependencies中我自己项目中引入的jar包 <proj ...

  3. softmax函数详解

    答案来自专栏:机器学习算法与自然语言处理 详解softmax函数以及相关求导过程 这几天学习了一下softmax激活函数,以及它的梯度求导过程,整理一下便于分享和交流. softmax函数 softm ...

  4. Linux 桌面玩家指南:03. 针对 Gnome 3 的 Linux 桌面进行美化

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  5. POS Tagging 标签类型查询表(Penn Treebank Project)

    在分析英文文本时,我们可能会关心文本当中每个词语的词性和在句中起到的作用.识别文本中各个单词词性的过程,可以称为词性标注. 英语主要的八种词性分别为: 1.名词(noun) 2.代词(pronoun) ...

  6. [JLOI2016] 成绩比较

    推石子 首先设\(d[i]=\sum_{t=1}^{U[i]}t^{n-R[i]}(U[i]-t)^{R[i]-1}\),即第\(i\)门课程分数的合法分布方案数: 然后设\(f[i,j]\)表示前\ ...

  7. 【视频】ASP.NET Core MVC 2.* 入门

    比较初级的入门教程,网址在B站:https://www.bilibili.com/video/av33728783/ 内容如下: 1. ASP.NET Core 简介和开发工具 2. ASP.NET ...

  8. 【Netty】(5)源码 Bootstrap

    [Netty]5 源码 Bootstrap 上一篇讲了AbstractBootstrap,为这篇做了个铺垫. 一.概述 Bootstrap 是 Netty 提供的一个便利的工厂类, 我们可以通过它来完 ...

  9. 【Android Studio安装部署系列】一、JDK开发环境搭建

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio安装后自带jre,这个自带jre的版本号肯定比最新的版本号要小. 但是如果项目中没有用到新版本jdk的特 ...

  10. SpringBoot启动原理及相关流程

    一.springboot启动原理及相关流程概览 springboot是基于spring的新型的轻量级框架,最厉害的地方当属自动配置.那我们就可以根据启动流程和相关原理来看看,如何实现传奇的自动配置 二 ...