数据结构学习之字符串匹配算法(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. windows手动去重 通配符

    在下载文件时,如果遇到重复文件,windows的默认做法时 文件名(数字) 这样的方式重命名的. 那么我们在排除重复文件时,可以使用  windows文件浏览器提供的查找功能,  用通配符   ~=& ...

  2. SQLServer之集合

    集合的定义 集合是由一个或多个元素构成的整体,在SQLServer中的表就代表着事实集合,而其中的查询就是在集合的基础上生成的结果集.SQL Server的集合包括交集(INTERSECT).并集(U ...

  3. Linux如何管理文档多租户

    例题 同一群组microsoft下的两个账号justmine001和justmine002需要共同拥有目录/microsoft/eshop的开发权,以便进行协同工作,但是其他人不允许进入和查阅该目录. ...

  4. pandas 对数据帧DataFrame中数据的索引及切片操作

    1.创建数据帧 index是行索引,即每一行的名字:columns是列索引,即每一列的名字.建立数据帧时行索引和列索引都需要以列表的形式传入. import pandas as pd df = pd. ...

  5. java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)

    在Java中,与线程通信相关的几个方法,是定义在Object中的,大家都知道Object是Java中所有类的超类 在Java中,所有的类都是Object,借助于一个统一的形式Object,显然在有些处 ...

  6. 粮草先行——Android折叠屏开发技术点(一)

    最近有关折叠屏产品的新闻层出不穷,各家手机厂商也分别慢慢地亮出了自家的产品.然而市场上的一些APP仍然没有很好地适配这样的设备,显示不正常和应用重启的状况时有发生.因此,我会用接下来的几篇文章来点出有 ...

  7. 杭电ACM2018--母牛的故事

    母牛的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  8. WinForm的EXE破解(基于IL修改)

    一.目的与目标 1.1 主题目的 部门新人较多,希望通过本次分享让同学们对以下知识点有个认识: 破解原理 IL原理 强签名与加密 resx文件 由于时间有限,本文作为部门分享演示过程中辅助性文档,会对 ...

  9. Java开发笔记(八十二)注解的基本单元——元注解

    Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...

  10. 网页三剑客:HTML+CSS+JavaScript 之JavaScript

    JavaScript 简介 JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器.PC.笔记本电脑.平板电脑和智能手机等设备. JavaScrip ...