简介:

一种由Knuth(D.E.Knuth)、Morris(J.H.Morris)和Pratt(V.R.Pratt)三人设计的线性时间字符串匹配算法。这个算法不用计算变迁函数δ,匹配时间为Θ(n),只用到辅助函数π[1,m],它是在Θ(m)时间内,根据模式预先计算出来的。数组π使得我们可以按需要,“现场”有效的计算(在平摊意义上来说)变迁函数δ。粗略地说,对任意状态q=0,1,…,m和任意字符a∈Σ,π[q]的值包含了与a无关但在计算δ(q,a)时需要的信息。由于数组π只有m个元素,而δ有Θ(m∣Σ∣)个值,所以通过预先计算π而不是δ,使得时间减少了一个Σ因子

以上摘自百度百科。。。

简单的来说,kmp就是一种高效的字符串匹配算法,它能够快速的处理出模式串与文本串的匹配

步骤:

预处理出nxt数组

首先,我们要明确数组的概念,我们定义nxt数组为最长真前后缀

即 \(nxt[i]=\{max(j)|s[1\,to\,j]=s[i-j+1\,to\,i]\}\)

这有什么用呢?

在传统的O(n^2)字符串匹配算法里,我们每次匹配失败时,就要重新跳到初始点匹配,然而事实上我们是不需要去这样匹配的

假设我们已经匹配到了模式串b的第j个字符,文本串a的第i-1个字符,发现\(b[j+1]\ne a[i]\),但我们可以知道\(b[1\,to\,j]=a[i-j\,to\,i-1]\),这个条件显然是可以利用的。

假如前面有一段,和我们匹配完的这一段是相等的,那么我们显然不需要再到\(b[1]\)去逐字匹配,我们可以直接跳到那一段的末尾,再来跟\(a[i]\)匹配,看是否相等

\(nxt\)数组就是来提供每次失配后跳的位置的,我们来看一下\(nxt\)数组

1 2 3 1 2 3 2

0 0 0 1 2 3 0

上面是模式串,下面是\(nxt\)数组,可以看图理解一下,以\(b[5]\)为例

那么,如何去得出\(nxt\)数组呢?

显然,是不能用暴力枚举的,否则时间复杂度还是O(n^2),就与我们的初衷相悖,所以我们要找到一种快速的处理出nxt数组的方式

假设我们已经求出了\(nxt[1\,to\,i-1]\),现在我们要求\(nxt[i]\),怎么快速的得到它的\(nxt\)值呢?

设\(j=nxt[i-1]\),即\(b[1\,to\,j]=b[i-j\,to\,j]\),那么只要\(b[j+1]=b[i]\),显然就可以得知\(nxt[i]=j+1\),否则,我们就令\(j=nxt[j]\),再来判断(因为这时nxt[j]~j之间的值都肯定不是,没理解的话可以自己画图理解)

代码实现:

void getnxt(){
nxt[1]=0;//数组下标从1开始,nxt[1]显然等于0
for(int i=2,j=0;i<=len;i++){
while(j>0&&b[i]!=b[j+1])j=nxt[j];
if(b[i]==b[j+1])j++;
nxt[i]=j;
}
}

例题:

Hdu1711 Number Sequence

显然,这道题只需要先把\(nxt\)数组处理出来,匹配的时候,如果匹配到模式串的末尾,就return

Code:

#include<bits/stdc++.h>
using namespace std;
#define N 1000100
int n,m,nxt[N],a[N],b[N];
void getnxt(){
nxt[1]=0;
for(int i=2,j=0;i<=m;i++){
while(j&&b[i]!=b[j+1]) j=nxt[j];
if(b[i]==b[j+1]) j++;
nxt[i]=j;
}
}
int kmp(){
int i=1,j=0;
while(i<=n){
while(j&&a[i]!=b[j+1]) j=nxt[j];
if(a[i]==b[j+1]) j++;
if(j==m) return i-m+1;
i++;
}
return -1;
}
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main(){
int Case=read();
begin:Case--;
if(Case<0)return 0;
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++)b[i]=read();
getnxt();printf("%d\n",kmp());
goto begin;
}

浅谈kmp的更多相关文章

  1. 浅谈KMP算法及其next[]数组

    KMP算法是众多优秀的模式串匹配算法中较早诞生的一个,也是相对最为人所知的一个. 算法实现简单,运行效率高,时间复杂度为O(n+m)(n和m分别为目标串和模式串的长度) 当字符串长度和字符集大小的比值 ...

  2. 【ZOJ】3785 What day is that day? ——浅谈KMP在ACM竞赛中的暴力打表找规律中的应用

    转载请声明出处:http://www.cnblogs.com/kevince/p/3887827.html    ——By Kevince 首先声明一下,这里的规律指的是循环,即找到最小循环周期. 这 ...

  3. 单模式串匹配----浅谈kmp算法

    模式串匹配,顾名思义,就是看一个串是否在另一个串中出现,出现了几次,在哪个位置出现: p.s.  模式串是前者,并且,我们称后一个 (也就是被匹配的串)为文本串: 在这篇博客的代码里,s1均为文本串, ...

  4. 浅谈KMP“串”的模式匹配问题

    感悟:预处理next[ ]数组求解B串的"自我匹配过程",思路与KMP类似,目标得到最大相同的前缀.后缀. ([1->k]==[i-k+1,i]),可以根据由前往后,利用前面 ...

  5. 浅谈KMP算法

    一.介绍 烤馍片KMP算法是用来处理字符串匹配问题的.比如说给你两个字符串A,B,问B是不是A的子串? 比如,eg就是aeggx的子串 一般讲字符串A称为主串,用来匹配的B串称为模式串 定义n为字符串 ...

  6. 【字符串算法3】浅谈KMP算法

    [字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述  [字符串算法3]KMP算法 Part1 理解KMP的精髓和思想 其实KM ...

  7. 【文文殿下】浅谈KMP算法next数组与循环节的关系

    KMP算法 KMP算法是一种字符串匹配算法,他可以在O(n+m)的时间内求出一个模式串在另一个模式串下出现的次数. KMP算法是利用next数组进行自匹配,然后来进行匹配的. Next数组 Next数 ...

  8. 浅谈KMP算法——Chemist

    很久以前就学过KMP,不过一直没有深入理解只是背代码,今天总结一下KMP算法来加深印象. 一.KMP算法介绍 KMP解决的问题:给你两个字符串A和B(|A|=n,|B|=m,n>m),询问一个字 ...

  9. 浅谈 KMP 算法

    最近在复习数据结构,学到了 KMP 算法这一章,似乎又迷糊了,记得第一次学习这个算法时,老师在课堂上讲得唾沫横飞,十分有激情,而我们在下面听得一脸懵比,啥?这是个啥算法?啥玩意?再去看看书,完全听不懂 ...

随机推荐

  1. Python学习之路:NumPy初识

    import numpy as np; //一维NumPy数组 myArray = np.array([1,2,3,4]); print(myArray); [1 2 3 4] //打印一维数组的形状 ...

  2. EasyUI系列学习笔记(一)——注册

    前面介绍过EasyUI是一个前段框架,开发之前需要导入底层包:我这里采用的是EasyUI 1.4版本~ 今天主要是搭建一个EasyUI的环境,同时做一个登陆页面... 环境搭建 导入需要的文件到项目中 ...

  3. Catlike学习笔记(1.2)-使用Unity画函数图像

    『Catlike系列教程』第二篇来了~今天周六,早上(上午11点)醒来去超市买了一周的零食回来以后就玩了一整天游戏非常有负罪感.现在晚上九点天还亮着感觉像下午7点左右的样子好像还不是很晚...所以就写 ...

  4. python破解网吧收费系统,远控网吧电脑设备!

      我今天呢 , 我就没事跟着朋友喝酒喝酒啊.喝了很多啊.晚上到旁边的酒店开了一个房间,到了酒店才十点! 感觉没啥事情干的,那就去网吧走走看把,看到是一个嘟嘟牛的,和上次是一样的.还是照常用MS170 ...

  5. Python中格式化format()方法详解

    Python中格式化format()方法详解 Python中格式化输出字符串使用format()函数, 字符串即类, 可以使用方法; Python是完全面向对象的语言, 任何东西都是对象; 字符串的参 ...

  6. js备忘录5

    函数的全解析 原文链接: http://mp.weixin.qq.com/s?src=11&timestamp=1509672643&ver=491&signature=9fD ...

  7. string类型的常用方法

    1. 在尾部插入/删除元素 string s("hello"); // 插入/删除一个字符 s.push_back('!'); s.pop_back(); // 插入多个字符 s. ...

  8. 20135234mqy 实验二 Java面向对象程序设计

      北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1352  姓名:mqy  学号:20135234 成绩:             指导教师: ...

  9. 学校网站UI设计分析

    在一个团队中PM,要更好的掌握项目的实施管理,包括对UI的设计,作为团队项目的PM,在听了老师课上的讲解后,对UI有了新的认识,对此,我对下面网站有了些自己的想法(只可意会不可言传,O(∩_∩)O~) ...

  10. java的(PO,VO,TO,BO,DAO,POJO)类名包名解释

    VO:值对象.视图对象 PO:持久对象 QO:查询对象 DAO:数据访问对象——同时还有DAO模式 DTO:数据传输对象——同时还有DTO模式 PO:全称是persistant object持久对象最 ...