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,时间复杂度大大降低↓↓↓。

至于代码:

想看代码可以直接看我的随笔《从2017暑假到现在辛苦打的模板》二十三

原文地址:https://www.cnblogs.com/fushao2yyj/p/8445290.html

时间: 2024-07-31 16:21:05

KMP字符串匹配算法翔解?的相关文章

KMP字符串匹配算法详解

KMP算法利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息.时间复杂度O(m+n). Next()函数的详解 把将要进行next计算的字符串S分成 k ,j 前后两串,k代表前串开头所在的序号,j代表后串开头所在的序号,起始的时候j=1,k=0. 我们比较一下前串 后串是否相等,要怎么比较呢,肯定是比较S[j]==S[k],如果相等,那么next[j+1]=k+1,然后j++,k++.关键就是理解这

KMP字符串匹配算法及next前缀数组的应用

#KMP字符串匹配算法及next前缀数组的应用------ KMP算法通常是我们学习字符串匹配算法时遇见的第一个算法,另外还有Rabin-Karp, Sunday算法等. 相对于其他字符串匹配算法, kmp在字符串中字符重复率低的情况下并不具备优势,那为什么KMP算法会作为经典的教学算法呢? 原因可能是:KMP算法充分利用next前缀数组的信息来优化算法,减小时间复杂度的思路在很多字符串相关问题中能给我们启发. 首先上KMP字符串匹配算法, [leetcode在线测试地址](https://le

(转)KMP字符串模式匹配详解

(转)KMP字符串模式匹配详解 个人觉得这篇文章是网上的介绍有关KMP算法更让人容易理解的文章了,确实说得很“详细”,耐心地把它看完肯定会有所收获的--,另外有关模式函数值next[i]确实有很多版本啊,在另外一些面向对象的算法描述书中也有失效函数 f(j)的说法,其实是一个意思,即next[j]=f(j-1)+1,不过还是next[j]这种表示法好理解啊: KMP字符串模式匹配详解 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n)

KMP字符串匹配算法——用最容易理解的方式描述

看了数据结构书上对于快速模式匹配算法KMP的介绍,感觉云里雾里.本文根据自己理解,并查资料整理了一种非常清晰简单的字符串匹配算法,并给予实现,自诩原创吧. 字符串匹配是我们经常要用到的一种算法,与普通的匹配算法相比KMP算法效率更高,时间复杂度为O(m+n).下面给予详细讲解: 概念详解 设原字符串为"BBC ABCDAB ABCDABCDABDE",待匹配字符串为"ABCDABD". 首先,字符串"BBC ABCDAB ABCDABCDABDE"

KMP字符串模式匹配详解

KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度为O(m+n).. 一.简单匹配算法 先来看一个简单匹配算法的函数: int Index_BF ( char S [ ], char T [ ], int pos ) { /* 若串 S 中从第pos(S 的下标0≤pos个字符 起存在和串 T 相同的子串,则称匹配成功,返回第一个 这样的子串在串 S 中的下标,否则返回 -1    */ int

【算法】KMP字符串匹配算法

[原理] (1)next数组原理 (2)特殊情况的处理(巧妙增设哨兵) (3)递推法构造next[]表 [实现代码] #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 100; char t[maxn]; //text char p[maxn]; int next[maxn]; void getNext(){ int m = strlen

算法学习——KMP字符串匹配算法

KMP算法是一种非常高效和常用的算法.其核心就是通过预处理一个寻找公共最大前后缀的 Next[ ] 数组,减少匹配失败时的重复无效匹配. next数组本质:next[ i ] = j 表示下标以 i - j 为起点,i为终点的后缀和下标以0为起点,j为终点的前缀相等. 复制一些别人的图片用来帮助理解next是什么. 然后是kmp算法的思想原理: 下图是主串为:ababaeaba 字串为:ababacd 的一个例子: 例题: 代码: #include<iostream> using namesp

KMP字符串匹配算法

1 #include<iostream> 2 #include<string> 3 #include<vector> 4 using namespace std; 5 bool matched(string s,int k,int i) 6 { 7 bool result=true; 8 int p=0; 9 int q=i; 10 while(p<k) 11 { 12 if(s[p]==s[q]) 13 { 14 p++;q--; 15 } 16 else 17

28. Implement strStr()(KMP字符串匹配算法)

Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Example 1: Input: haystack = "hello", needle = "ll" Output: 2 Example 2: Input: haystack = "aaaaa",