KMP算法讲解

转载自傅少博客

那么首先我们知道,kmp算法是一种字符串匹配算法,那么我们来看一个例子。

比方说,现在我有两段像这样子的字符串:

分别是T和P,很明显,P比T的长度要短很多,我们要做的事情呢,就是找找T中有没有和P相同的一段。

如果按照最简单的办法来做匹配的话,我们一般是一个一个字母的来做。

像这样:

很显然,图中前面3位都是能匹配的,而第四位却不能匹配,怎么办?

这样:

我们就会将整个P字符串向右移动一格,又重新开始,从T中b处与P中第一个a处开始匹配。

如此往复,显然这样是很慢的,因为我们来考虑考虑这样一种极端的情况:

像这样,显然一位一位匹配是会做许多重复的操作的。

那么现在我们来考虑使用一下kmp算法。

怎么做呢?

首先我们需要处理一个叫做前缀表(prefix table)的东西(有些博客说是next[]数组,其实是一样的)。

什么是前缀呢?比如说,P字符串为a b a b c,那么P的前缀即为a,a b,a b a,a b a b和a b a b c共五个。

所以,做kmp算法时,我们先要把我们要搜索的那一个字符串的所有前缀都写出来。这是第一步。

好,那么第二步,我们就要将之前处理出的所有前缀当做不同的几个字符串。

然后,我们对每个这样的前缀字符串处理一下,处理出一个叫做最长公共前后缀的东西。

最长公共前后缀是比原来字符串要短的前缀与后缀最长公共部分的长度,这是什么意思呢?听起来特别拗口。

比方说,我们来看看第四个前缀字符串。很显然,它的最长前缀是a b a,最长后缀是b a b(忽略本身)。

明显这两者是不同的,所以长度取3时是不行的。那么我们取2,此时前缀是a b,后缀是a b,二者相等。

这时我们就将2称作字符串a b a b的最长公共前后缀。

如图,我们处理出了前缀表中的所有最长公共前后缀。

而在KMP算法中,前缀表里长度等于本身的那个并不需要处理,舍去,而需要在最上面添加一个-1。

(等下模拟时,其作用就显而易见了)。

现在我们已经处理好了prefix table,即-1 0 0 1 2 0。

接下来,进行第三步,将prefix table与P字符串对应,并标好下标index

1、          2、

如图,上层是index,下层是prefix。

然后,我们模拟一下KMP算法是如何利用处理好的前缀表来计算运行的。

如图,前面3位,我们还是如之前一样完美匹配,但是到了第四位,就匹配不了了,怎么办呢?

不同以往,我们不再是往右移一格,而是跳到这一位对应的prefix所指的index处,[email protected]#$%^&*...好绕啊啊啊!

上图吧:

此时待匹配的位置的index,是不是就是之前发生错误的那个第四位所对应的prefix呢?

这样,我们便可以直接从P中第二位开始重新匹配啦!!!

p.s.忘了说了,如果prefix是-1,那么就直接向右移一格。

真是神奇讷、

不知道读者是否还记得之前提出的极端情况。

如果用KMP算法,处理好前缀表后,是不是这样:

所以 当匹配到a b时,那么就直接会跳到index为3的a处,而跳过匹配前面3个a,时间复杂度大大降低↓↓↓。

原文地址:https://www.cnblogs.com/BCOI/p/8460721.html

时间: 2024-09-30 07:16:49

KMP算法讲解的相关文章

[转]一个比较通俗的KMP算法讲解

最近在学字符串匹配的时候接触了这个算法,算法书上都是我讨厌的下标,转来转去,头晕啊.只好上网搜一下,大部分跟书上一样,好不容易找到一篇,总算看得有些懂了.      其实最简单的字符串匹配,就是逐个逐个比较,但是这样的效率很低,而KMP算法利用了......(不说了,表达能力差啊,^_^,看看牛人怎么解释的吧). 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串

KMP 算法 java实现

KMP算法讲解 我的Java代码实现 package jj4_6; public class KMP { public static boolean contains(String a,String b){ /* * 第一步,对b字符串做一个预处理 */ Integer[] fuzhu = new Integer[b.length()]; for(Integer i= 0;i<b.length();i++){ // i == 3 时 // nowstr = "abab" Stri

KMP算法应用举例

KMP是字符串匹配的经典算法 也是众多字符串基础的重中之重 A. 题意:给T组数据,每组有长度为n和m的母串和模式串.判断模式串是否是母串的子串,如果是输出最先匹配完成的位置,否则输出-1. 做法:直接套用模板.把char改成int.kmp函数中在模式串遍历到结尾的时候return,若没遍历到结尾,也就是不是子串返回-1 1 [cpp] view plain copy 2 #include <iostream> 3 #include <cstdio> 4 #include <

【原创】通俗易懂的讲解KMP算法及代码实现

一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想后的优化. 所以本文重点是讲解KMP算法的核心,文章最后会有涉及一些改良过程. 二.KMP算法简介 KMP算法是字符串匹配算法的一种.它以三个发明者命名,Knuth-Morris-Pratt,起头的那个K就是著名科学家Donald Knuth. 三.KMP算法行走过程 首先我们先定义两个字符串作为示

KMP算法通俗讲解

最近对KMP算法好奇,这算法完全没印象(学校教过,但我没学,因为逃课),也不是还给了老师.只是想跳槽的话,听说都得明白这玩意. 在网上找了一篇文章,这哥们应该算是比较出名的,http://www.matrix67.com/blog/archives/115. 刚开始看,一个字“晕”.什么kmp,bf,bm,头都看疼了.仔细看了后才明白.下面说说bf与kmp,没有代码,尽量通俗点讲解. bf不细说了,这是相当"通俗"及自然(我自己形容为原始想法)的想法,从头到尾比较字符串,不相等则从头再

KMP算法详解

这几天学习kmp算法,解决字符串的匹配问题,开始的时候都是用到BF算法,(BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果.BF算法是一种蛮力算法.)虽然也能解决一些问题,但是这是常规思路,在内存大,数据量小,时间长的情况下,还能解决一些问题,但是如果遇到一些限制时间和内存的字符串问

(转载)KMP算法详解(写的很好)

原文地址:http://www.cnblogs.com/yjiyjige/p/3263858.html KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么一回事,但总感觉有些地方自己还是没有完全懂明白.这两天花了点时间总结一下,有点小体会,我希望可以通过我自己的语言来把这个算法的一些细节梳理清楚,也算是考验一下自己有真正理解这个算法. 什么是KMP算法: K

KMP算法的理解

---恢复内容开始--- 在看数据结构的串的讲解的时候,讲到了KMP算法——一个经典的字符串匹配的算法,具体背景自行百度之,是一个很牛的图灵奖得主和他的学生提出的. 一开始看算法的时候很困惑,但是算法思想很简单,就是在暴力匹配的基础上得出的. 暴力匹配 这里有必要说一下暴力匹配,暴力匹配更简单,就是按照人的常规思维去匹配字符串,拿模式串(P)的第一个字符去和给定串(S)比较,S从左往右看,一看,第一个,呀~不对,啥也不说了,第一个都不对了,后边还比个毛.所以,这一次比较,S中第一个字符开头是匹配

KMP算法实现字符串匹配

#include<stdio.h> #include<string> #include<iostream> using namespace std; int main() { string str,p; cin>>str>>p; int n=str.length(); int m=p.length(); //compute prefix function int pre[100]; pre[0]=-1; int k=-1; for(int j=1