KMP瞎扯一下
什么是KMP
KMP俗称看毛片算法,是高效寻找匹配字串的一个算法
百度百科
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
总的来说这个东西是一个加速优化的算法,而且这三个大佬能发现这个算法实在是太强大了!!!
怎么实现KMP?
next数组的实现(失配数组)
具体高大上的来说就是什么字串的前缀和和后缀和相等的最大长度,实际上这个东西就是寻找如果匹配失效怎么高速寻找下一个位置的数组。具体来说就像是一个规律一样。
具体代码
//我们规定next数组回溯如果为0,那么就是不存在。而且原字符串数组也是从第一位开始的,也就是说原字符串数组的位数跟数组的下标是一致的。
//所以说next数组回溯寻找的位置就是数组下标的位置
for(int i=2;i<=lb;i++)//i=1的时候默认回溯的就是0,所以从i=2开始寻找
{
while(j&&b[i]!=b[j+1])//j!=0的意思是j如果回溯到0的话不要让j再继续回溯,第二个条件就是自己匹配自己,这个地方是一个规律性的写法,可以自己手写模拟一下,十分的巧妙
j=next[j];//如果匹配失败,回溯到之前的位置继续匹配,而不是直接从0开始。这也是一个优化
if(b[i]==b[j+1])//如果匹配成功,j就加一继续继续寻找
j++;
next[i]=j;//每一次都得记录next数组的回溯位置
}
匹配的实现(应用next数组)
具体的代码
j=0;//j从第0位开始
for(int i=1;i<=la;i++)//因为上面已经说过数组的字符位数就是字符串数组的第几位所以从1开始循环
{
while(j&&a[i]!=b[j+1])//如果失配回溯j,进行高效的寻找
j=next[j];
if(a[i]==b[j+1])//如果匹配成功就让j++
j++;
if(j==lb)//如果j等于原先字串的长度那么就算匹配成功
{
cout<<i-lb+1<<"\n";//别忘记i也在一直循环++
j=next[j];//回溯到之前的位置
}
}
完整代码(模板题 洛谷P3375 【模板】KMP字符串匹配)
#include <bits/stdc++.h>
using namespace std;
int next[1000010];
char a[1000010];
char b[1000010];
int main()
{
ios::sync_with_stdio(0);//关闭同步三步走
cin.tie(0);cout.tie(0);
cin>>a+1>>b+1;//从第一位输入
int la=strlen(a+1);//计算长度
int lb=strlen(b+1);
int j=0;//定义j
//我们规定next数组回溯如果为0,那么就是不存在。而且原字符串数组也是从第一位开始的,也就是说原字符串数组的位数跟数组的下标是一致的。
//所以说next数组回溯寻找的位置就是数组下标的位置
for(int i=2;i<=lb;i++)//i=1的时候默认回溯的就是0,所以从i=2开始寻找
{
while(j&&b[i]!=b[j+1])//j!=0的意思是j如果回溯到0的话不要让j再继续回溯,第二个条件就是自己匹配自己,这个地方是一个规律性的写法,可以自己手写模拟一下,十分的巧妙
j=next[j];//如果匹配失败,回溯到之前的位置继续匹配,而不是直接从0开始。这也是一个优化
if(b[i]==b[j+1])//如果匹配成功,j就加一继续继续寻找
j++;
next[i]=j;//每一次都得记录next数组的回溯位置
}
j=0;//j从第0位开始
for(int i=1;i<=la;i++)//因为上面已经说过数组的字符位数就是字符串数组的第几位所以从1开始循环
{
while(j&&a[i]!=b[j+1])//如果失配回溯j,进行高效的寻找
j=next[j];
if(a[i]==b[j+1])//如果匹配成功就让j++
j++;
if(j==lb)//如果j等于原先字串的长度那么就算匹配成功
{
cout<<i-lb+1<<"\n";//别忘记i也在一直循环++
j=next[j];//回溯到之前的位置
}
}
for(int i=1;i<=lb;i++)//这里是输出next数组的
cout<<next[i]<<" ";
return 0;//结束
}
总结
对于朴素的BF算法来说,从时间复杂度O(mn)降低到了O(m+n),之后还KMP的拓展算法,等以后在补坑了例如sunday算法,不过对于能发现这个算法的人来说,实在是太强大了
KMP瞎扯一下的更多相关文章
- 瞎扯KMP
瞎扯\(KMP\) 众所周知,\(KMP\)是一种玄学的字符串模式匹配算法. 什么是字符串模式匹配? 通俗的讲,就是统计一个字符串(通常很长)中某个子串(即一段连续的字符)出现的次数或位置.一般来说, ...
- KMP算法求解
// KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...
- 简单有效的kmp算法
以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...
- KMP算法
KMP算法是字符串模式匹配当中最经典的算法,原来大二学数据结构的有讲,但是当时只是记住了原理,但不知道代码实现,今天终于是完成了KMP的代码实现.原理KMP的原理其实很简单,给定一个字符串和一个模式串 ...
- 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)
前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...
- [KMP]【学习笔记】
Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 36916 Accepted: 14904 Descript ...
- KMP算法实现
链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...
- KMP专题
1.[HDU 3336]Count the string(KMP+dp) 题意:求给定字符串含前缀的数量,如输入字符串abab,前缀是a.ab.aba.abab,在原字符串中出现的次数分别是2.2.1 ...
- KMP学习之旅
说起kmp就要从字符串的匹配说起,下面我们谈谈字符串的匹配 给定一个原字符串:bababababababababb,再给定一个模式串:bababb,求模式串是否在源字符串中出现 最简单的方法就是遍历源 ...
随机推荐
- 【转】pthread_cond_signal 虚假唤醒问题
引用:http://blog.csdn.net/leeds1993/article/details/52738845 什么是虚假唤醒? 举个例子,我们现在有一个生产者-消费者队列和三个线程. I.1号 ...
- Struts数据验证
Action类继承了ActionSupport类,而该类实现了Action.Validateable.ValidationAware.TextProvider.LocaleProvider和Seria ...
- HTTPS数据包抓取的可行性分析
HTTPS数据包抓取的可行性分析 相信只要是从事软件开发, 多多少少都会涉及到数据包的抓取.常见的有网页数据抓取(即网页爬虫),应用程序数据包抓取等.网页数据抓取比较简单, 在chrome下可以非常方 ...
- git服务器的建立
git简介 首先,与以前广为流行的SVN不同,git是分布式的,其没有服务器端与客户端之分(虽然在项目管理过程中,一般会人为地指定某一台非开发用的机器作为“服务器”,但就git自身功能来说,完全可以没 ...
- mac apache虚拟主机配置
<VirtualHost *:80> ServerAdmin slin DocumentRoot "/Users/slin/work/phpStudy/myPh ...
- 一句powershell调用mimikatz抓密码
mimikatz神器大家都知道吧,可以抓取系统内的明文密码,但是平时我们测试的时候需要把mimikatz的几个文件上传到目标系统上面,然后再手工执行几个命令才能搞定,今天无意访问一个大神的博客,发现其 ...
- 一个简陋的个人小项目,也是个人第一个真正意义上的独立项目——Graph
由来 我最早接触到图这个概念是在大二的离散数学当中图论相关的内容,当时是以著名的哥尼斯堡七桥问题引出图论的概念,现在依然记忆犹新(不过只是记得这个名字,具体的解题思路我重新温习了一下才想起来),当时也 ...
- Hadoop伪分布式模式搭建
title: Hadoop伪分布式模式搭建 Quitters never win and winners never quit. 运行环境: Ubuntu18.10-server版镜像:ubuntu- ...
- 为什么前后端分离不利于seo
搜索引擎的基础爬虫的原理就是抓取你的url,然后获取你的html源代码并解析. 而你的页面通常用了vue等js的数据绑定机制来展示页面数据,爬虫获取到的html是你的模型页面而不是最终数据的渲染页面, ...
- redis在linux的安装和开机启动(二)
编译 安装 makefile已经存在 执行make 即可 make之后, 自动创建可运行的脚本文件, 不需要再执行 install了. 将脚本文件, 拷贝到指定位置, 就可以了. 手动创建目录, 需要 ...