【算法•日更•第三十一期】KMP算法
▎前言
这次要讲的HMP算法KMP算法很简单,是用于处理字符串的,之前一直以为很难,其实也不过如此(说白了就是优化一下暴力)。
▎处理的问题
通常处理的问题是这样的:给定两个字符串s1和s2,其中s1是文本串,s2是匹配串,求s2在s1中出现的位置。
举个例子:(方便起见,下标从1开始)比如说s1是AABAAC,s2是BA,那么s2在s1的第3个位置处出现。
▎暴力求解
如何使用暴力求解这道题呢?我们只要分别暴力遍历两个字符串,然后分别比对当前字符,如果相等就继续比下去,如果不相等,那么s1回溯回没有执行这一次比对的位置,s2遍历的位置归零。
代码如下,详见注释:
#include<iostream>
using namespace std;
string s1,s2;int i=,j=;
int main()
{
cin>>s1;cin>>s2;
int len1=s1.length();int len2=s2.length();
while(i<len1&&j<len2)
{
if(s1[i]==s2[j])
{
i++;
j++;
}
else
{
i=i-j+;
j=;
}
}
if(j==len2) cout<<i-j;
else cout<<"No answer";
return ;
}
▎KMP算法
☞『定义』
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)。(copy自百度)
说白了就是把暴力求解的过程优化一下。
☞『算法核心』
仔细思考一下,为什么暴力求解效率不高呢?
这个问题很好回答,因为我们直接比对失败后就抛弃了,因此没有利用到这些匹配失败的东西,如果我们能够合理的利用,在失败的基础上继续比对,那么就可以优化了。
KMP算法不同于暴力的地方就在于把比对失败的当前遍历的字符串准确找到一个之前信息一样的字符串,继续比对。
比如说s1是AABAAC,s2是AB,在遍历到AA时发现不同,那么之前相同的是A,那么跳转到下一个A所在的位置继续比对,也就是跳到了第二个A的位置,发现相同,那么就找到了。
其余的与暴力相同,只不过跳转就成为了一大难点。
那么我们现在来考虑如何跳转,我们可以使用一个数组(next)来存储当前信息相同的位置,那么我们可以定义两个指针(不是语法中的指针,此指针非彼指针),初始化一个在0,一个在-1。
如果一个在-1(还没有开始比对,或者跳转到了这里)或者当前字符相同,那么就继续比对。否则就将其中一个跳转。
总而言之看代码吧。
☞『代码如下』
#include<iostream>
#include<cstring>
using namespace std;
char s1[],s2[];int i=-,j=,next[];
int main()
{
cin>>s1;cin>>s2;
int len1=strlen(s1);int len2=strlen(s2);//输入字符串
next[]=-;//初始化
while(j<len2-)
{
if(i==-||s2[i]==s2[j])//-1可能是初始状态的,也可能是跳过来的
{
i++;
j++;
next[j]=i;//顺便记录下来
}
else i=next[i];//跳到另一个信息一样的地方
}
i=;j=;
while(i<len1&&j<len2)//常规操作
{
if(j==-||s1[i]==s2[j])
{
i++;
j++;
}
else j=next[j];//跳转
}
if(j==len2) cout<<i-j;
else cout<<"No answer";
return ;
}
【算法•日更•第三十一期】KMP算法的更多相关文章
- 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解
废话不多说,直接上题: P4170 [CQOI2007]涂色 题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符 ...
- 【算法•日更•第三十九期】迭代加深搜索:洛谷SP7579 YOKOF - Power Calculus 题解
废话不多说,直接上题: SP7579 YOKOF - Power Calculus 题意翻译 (略过没有营养的题干) 题目大意: 给出正整数n,若只能使用乘法或除法,输出使x经过运算(自己乘或除自己, ...
- 【算法•日更•第三十五期】FF算法优化:EK算法
▎写在前面 FF算法传送门 之前我们已经学过了FF算法(全称Ford-Fulkerson算法)来找最大流,但是这种算法仍有诸多不对的地方. 其实这种算法存在着严重的效率的问题,请看下面的图: 以这个图 ...
- 【算法•日更•第三十二期】教你用出windows体验的Linux
▎前言 小编昨天闲的不行,就装了一个linux系统,linux的发行版很多,小编认为ubuntu很好用,于是就在使用ubuntu. 没错,我现在就在使用ubuntu来写博客. 刚才还装了一个QQ,不过 ...
- 【算法•日更•第五十期】二分图(km算法)
▎前言 戳开这个链接看看,惊不惊喜,意不意外?传送门. 没想到我的博客竟然被别人据为己有了,还没办法投诉. 这年头写个博客太难了~~~ 之前小编写过了二分图的一些基础知识和匈牙利算法,今天来讲一讲km ...
- 【算法•日更•第五十四期】知识扫盲:什么是operator?
▎前言 这个东西和迭代器长的很像,但是比迭代器常见的多. 今天就来浅谈operator. ▎定义 operator是C#.C++和pascal的关键字,它和运算符一起使用,表示一个运算符函数,理解时应 ...
- 【算法•日更•第三十七期】A*寻路算法
▎写在前面 这是一种搜索算法,小编以前总是念成A乘寻路算法,没想到一直念错. 请大家都念成A星寻路算法,不要像小编一样丢人了. ▎A*寻路算法 ☞『引入』 相信大家都或多或少的玩过一些游戏吧,那么游戏 ...
- 【算法•日更•第四十二期】离散傅里叶变换(DFT)
▎前言 小编相当的菜,这篇博客难度稍高,所以有些可能不会带有证明,博客中更多的是定义. 我们将要学到的东西: 复数 暴力多项式乘法 DFT 当然,小编之前就已经写过一篇博客了,主要讲的就是基础多项式, ...
- 【算法•日更•第四十三期】QQ for linux
废话不多说,直接看一张图: 没错,这是QQ,但是这有什么稀奇的?但是在Linux上使用QQ就很稀奇了. 众所周知,腾讯早就已经对Linux下的QQ和微信停止了服务,即便是网页版也不能用,通信这一直是小 ...
随机推荐
- Makefile中自动生成头文件依赖
为什么需要自动生成头文件依赖? 编译单个源文件时,需要获取文件中包含的头文件的信息,但是一般的Makefile不会在规则中明确写明文件依赖的头文件,所以单独修改头文件后,不会导致包含头文件的源文件重新 ...
- CentOS7上安装Hadoop
设置sshssh-keygen -t rsa -P ''cat id_rsa.pub >> authorized_keys 查看slaves节点的id_rsa.pub文件,将文件内容复制到 ...
- 感知机算法(PLA)代码实现
目录 1. 引言 2. 载入库和数据处理 3. 感知机的原始形式 4. 感知机的对偶形式 5. 多分类情况-one vs. rest 6. 多分类情况-one vs. one 7. sklearn实现 ...
- 最简单的VScode Python 开发环境配置以及中文化
前置条件 Python 3.X(2020年了,建议使用Python3.X版本) 一.下载VSCode VSCode官方下载链接 由于安装过程是中文界面,此处略过. 二.VSCode中文化 不需要配置什 ...
- 使用iOS网络请求
https://github.com/yuantiku/YTKNetwork/blob/master/Docs/2.0_MigrationGuide_cn.md
- express中post请求模块
body-parser模块主要解析post接口请求 1.npm install body-parser -S 2.server.js中引用 const bodyParser=require('bo ...
- LVS+Keepalived 实现高可用负载均衡
前言 在业务量达到一定量的时候,往往单机的服务是会出现瓶颈的.此时最常见的方式就是通过负载均衡来进行横向扩展.其中我们最常用的软件就是 Nginx.通过其反向代理的能力能够轻松实现负载均衡,当有服务出 ...
- layer弹窗插件留言提交
function msgShow(getname,getuserid){ layer.open({ type: 1 //此处以iframe举例 ,title: '收件人:'+getname+'(ID: ...
- Day03_破解Windows7系统密码&用户与组管理&服务器远程管理
破解Windows系统密码 一.利用5次shift漏洞破解win7密码 1.1 漏洞 1.在未登录系统时,连续按5次shift键,弹出程序c:\windows\system32\sethc.exe 2 ...
- Python os.dup2() 方法
概述 os.dup2() 方法用于将一个文件描述符 fd 复制到另一个 fd2.高佣联盟 www.cgewang.com Unix, Windows 上可用. 语法 dup2()方法语法格式如下: o ...