kmp算法 公式

合集下载

python 字符串匹配算法 百分比

python 字符串匹配算法 百分比

python 字符串匹配算法百分比一、暴力匹配算法暴力匹配算法,也称为朴素匹配算法,是最简单直观的字符串匹配算法。

其基本思想是从主串的第一个字符开始,依次与模式串的每个字符进行比较,若出现不匹配的字符,则主串的指针向后移动一位,模式串的指针重新指向模式串的首字符,继续比较。

直到找到匹配的子串或主串遍历完成。

暴力匹配算法的时间复杂度为O(m*n),其中m为主串的长度,n为模式串的长度。

虽然暴力匹配算法简单易实现,但在处理大规模的字符串匹配时效率较低。

二、KMP算法KMP算法是一种高效的字符串匹配算法,它利用模式串的信息,避免了不必要的比较。

KMP算法的核心是构建一个部分匹配表,该表记录了模式串中每个前缀的最长真前缀与最长真后缀的匹配长度。

在匹配过程中,当出现不匹配的字符时,根据部分匹配表的信息,将模式串向右移动一定的位数,从而减少了比较次数。

KMP算法的时间复杂度为O(m+n),其中m为主串的长度,n为模式串的长度。

相比暴力匹配算法,KMP算法大大提升了匹配的效率。

三、Boyer-Moore算法Boyer-Moore算法是一种基于启发式思想的字符串匹配算法,它通过预处理模式串,构建两个规则数组,分别记录了坏字符规则和好后缀规则。

在匹配过程中,根据规则数组的信息,将模式串向右移动一定的位数,从而跳过不可能匹配的位置,提高匹配效率。

Boyer-Moore算法的时间复杂度为O(m+n),其中m为主串的长度,n 为模式串的长度。

相比KMP算法,Boyer-Moore算法在某些情况下具有更好的性能。

四、Rabin-Karp算法Rabin-Karp算法是一种基于哈希的字符串匹配算法,它通过计算主串和模式串的哈希值,进行匹配。

在匹配过程中,通过比较哈希值来判断是否匹配,从而减少了具体字符的比较次数。

Rabin-Karp算法的时间复杂度为O(m+n),其中m为主串的长度,n 为模式串的长度。

相比于前面介绍的算法,Rabin-Karp算法在处理大规模字符串匹配时具有较好的性能。

KMP讲解

KMP讲解
2.2、kmp算法
有了覆盖函数,那么实现kmp算法就是很简单的了,我们的原则还是从左向右匹配,但是当失配发生时,我们不用把target_index向回移动,target_index前面已经匹配过的部分在pattern自身就能体现出来,只要动pattern_index就可以了。
当发生在j长度失配时,只要把pattern向右移动j-overlay(j)长度就可以了。
说了这么半天那么这种方法是什么呢,这种方法是就大名鼎鼎的确定的有限自动机(Deterministic finite state automaton DFA),DFA可识别的文法是3型文法,又叫正规文法或是正则文法,既然可以识别正则文法,那么识别确定的字串肯定不是问题(确定字串是正则式的一个子集)。对于如何构造DFA,是有一个完整的算法,这里不做介绍了。在识别确定的字串时使用DFA实在是大材小用,DFA可以识别更加通用的正则表达式,而用通用的构建DFA的方法来识别确定的字串,那这个overhead就显得太大了。
{
index = overlay_value[index];
}
if(pattern[index+1]==pattern[i])
{
overlay_value[i] = index +1;
KMP 算法可在O(n+m)时间内完成全部的串的模式匹配工作。
ok,最后给出KMP算法实现的c++代码:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int kmp_find(const string& target,const string& pattern)

kmp算法python代码

kmp算法python代码

kmp算法python代码摘要:1.KMP 算法简介2.KMP 算法的Python 实现3.KMP 算法的应用示例正文:1.KMP 算法简介KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用于在一个主字符串中查找一个子字符串出现的位置。

该算法的关键在于通过预处理子字符串,减少不必要的字符比较,从而提高匹配速度。

2.KMP 算法的Python 实现以下是KMP 算法的Python 实现:```pythondef compute_prefix_function(pattern):m = len(pattern)prefix_function = [0] * (m + 1)prefix_function[0] = 0i, j = 1, 0while i < m:if pattern[i] == pattern[j]:j += 1prefix_function[i] = ji += 1else:if j!= 0:j = prefix_function[j - 1]else:prefix_function[i] = 0i += 1return prefix_functiondef kmp_search(text, pattern):m, n = len(text), len(pattern)prefix_function = compute_prefix_function(pattern) i, j = 0, 0while i < m:if pattern[j] == text[i]:i += 1j += 1if j == n:return i - jelif i < m and pattern[j]!= text[i]:if j!= 0:j = prefix_function[j - 1]else:i += 1return -1if __name__ == "__main__":text = "我国是一个伟大的国家"pattern = "伟大的"result = kmp_search(text, pattern)if result!= -1:print("子字符串"{}" 在主字符串中第{} 位置出现。

不同的模式匹配方法详解(暴力、KMP、Rabin-Karp算法)

不同的模式匹配方法详解(暴力、KMP、Rabin-Karp算法)

不同的模式匹配⽅法详解(暴⼒、KMP、Rabin-Karp算法)1 概述单模式匹配是处理字符串的经典问题,指在给定字符串中寻找是否含有某⼀给定的字串。

⽐较形象的是CPP中的strStr()函数,Java的String 类下的indexOf()函数都实现了这个功能,本⽂讨论⼏种实现单模式匹配的⽅法,包括暴⼒匹配⽅法、KMP⽅法、以及Rabin-Karp⽅法(虽然Rabin-Karp⽅法在单模式匹配中性能⼀般,单其多模式匹配效率较⾼,且采取⾮直接⽐较的⽅法也值得借鉴)。

算法预处理时间匹配时间暴⼒匹配法O(mn)KMP O(m)O(n)Rabin-Karp O(m)O(mn)2 暴⼒匹配模式匹配类的问题做法都是类似使⽤⼀个匹配的滑动窗⼝,失配时改变移动匹配窗⼝,具体的暴⼒的做法是,两个指针分别指向长串的开始、短串的开始,依次⽐较字符是否相等,当不相等时,指向短串的指针移动,当短串指针已经指向末尾时,完成匹配返回结果。

以leetcode为例给出实现代码(下同)class Solution {public int strStr(String haystack, String needle) {int m = haystack.length(), n = needle.length();if (needle.length() == 0) return 0;for (int i = 0; i <= m - n; i++) {for (int j = 0; j < n; j++) {if (haystack.charAt(i + j) != needle.charAt(j))break;if (j == n - 1)return i;}}return -1;}}值得注意的是,Java中的indexO()⽅法即采⽤了暴⼒匹配⽅法,尽管其算法复杂度⽐起下⾯要谈到的KMP⽅法要⾼上许多。

⼀个可能的解释是,⽇常使⽤此⽅法过程中串的长度都⽐较短,⽽KMP⽅法预处理要⽣成next数组浪费时间。

kmp 回文串

kmp 回文串

kmp 回文串
摘要:
1.KMP 算法简介
2.KMP 算法与回文串的关系
3.KMP 算法在回文串检测中的应用
4.KMP 算法的优缺点
5.总结
正文:
一、KMP 算法简介
KMP(Knuth-Morris-Pratt)算法是一种字符串匹配算法,用于在一个主字符串中查找一个子字符串出现的位置。

该算法的关键在于通过预处理子字符串,减少不必要的字符比较,从而提高匹配效率。

二、KMP 算法与回文串的关系
回文串是指一个字符串从前往后和从后往前读都是一样的,例如“level”和“racecar”都是回文串。

KMP 算法在处理回文串时,具有较高的效率。

因为回文串的特性是前缀和后缀相同,这使得在查找子字符串时,可以利用部分匹配值来避免无效的匹配。

三、KMP 算法在回文串检测中的应用
KMP 算法在回文串检测中的应用非常广泛。

具体来说,可以通过KMP 算法来检测一个给定的字符串是否是回文串。

如果一个字符串是回文串,那么它在反转后与原串相等。

因此,我们可以使用KMP 算法在一个字符串中查找
其反转后的子串,如果找到,则说明该字符串是回文串。

四、KMP 算法的优缺点
KMP 算法的优点是高效,尤其是在处理回文串时。

通过预处理子字符串,可以避免无效的匹配,从而提高匹配速度。

然而,KMP 算法也有其缺点,即需要预处理子字符串,这可能会导致额外的时间开销。

五、总结
KMP 算法是一种高效的字符串匹配算法,尤其适用于回文串检测。

通过预处理子字符串,可以减少无效的匹配,提高匹配效率。

KMP

KMP

KMP算法
next函数的改进 函数的改进
aaabaaaab aaaa ① ② ③
j=4 j=3 j=2 j=1 i=4
j
12345
模式 a a a a b next[j] 0 1 2 3 4 nextval[j] 0 0 0 0 4
aaa aa a
aaaab i = 5; j = 1
next[j] = k,而pj=pk, , 主串中s 不等时, 则 主串中 i和pj不等时, 不需再和p 进行比较, 不需再和 k进行比较, 而直接和p 而直接和 next[k]进行比 较.
第 1 次匹配 s= cddcdc t=cdc 第 2 次匹配 s= cddcdc t=cdc 第 3 次匹配 s= cddcdc t=cdc 第 4 次匹配 s= cddcdc t=cdc i= 3 j= 3 i= 2 j= 1 i= 3 j= 1 i= 6 j= 3 成功 失败 失败 失败
i = i –j +2; j = 1;
KMP算法
j 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 模式串 a b c a a b b c a b c a a b d a b next[j] 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2
nextval[j]
0 1 1 0 2 1 3 1 0 1 1 0 2 1 7 0 1
KMP算法
KMP算法的时间复杂度 KMP算法的时间复杂度 设主串s 的长度为n, 模式串t 长度为m, KMP算 n,模式串 m,在 设主串 s 的长度为 n, 模式串 t 长度为 m, 在 KMP 算 法中求next 数组的时间复杂度为 O(m),在后面的匹 法中求 next数组的时间复杂度为 O(m), 在后面的匹 next 数组的时间复杂度为O(m), 配中因主串s的下标不减即不回溯,比较次数可记为 配中因主串s的下标不减即不回溯, n,所以KMP算法总的时间复杂度为O(n+m). n,所以KMP算法总的时间复杂度为O(n+m). 所以KMP算法总的时间复杂度为O(n+m)

kmp next算法

kmp next算法

kmp next算法KMP算法(Knuth-Morris-Pratt Algorithm)是一种字符串匹配算法,它的核心思想是利用已经得到的匹配结果,尽量减少字符的比较次数,提高匹配效率。

本文将详细介绍KMP算法的原理、实现方法以及应用场景。

一、KMP算法的原理KMP算法的核心是构建next数组,用于指导匹配过程中的回溯操作。

next数组的定义是:对于模式串中的每个字符,记录它前面的子串中相同前缀和后缀的最大长度。

next数组的长度等于模式串的长度。

具体来说,KMP算法的匹配过程如下:1. 初始化主串指针i和模式串指针j为0。

2. 逐个比较主串和模式串对应位置的字符:- 若主串和模式串的字符相等,i和j同时后移一位。

- 若主串和模式串的字符不相等,根据next数组的值,将模式串指针j回溯到合适的位置,继续匹配。

二、KMP算法的实现KMP算法的实现可以分为两个步骤:构建next数组和利用next数组进行匹配。

1. 构建next数组:- 首先,next[0]赋值为-1,next[1]赋值为0。

- 然后,从第2个位置开始依次计算next[i],根据前一个位置的next值和模式串的字符进行判断:- 若前一个位置的next值为-1或模式串的字符与前一个位置的字符相等,则next[i] = next[i-1] + 1。

- 若前一个位置的next值不为-1且模式串的字符与前一个位置的字符不相等,则通过next数组的回溯操作,将模式串指针j回溯到合适的位置,继续判断。

2. 利用next数组进行匹配:- 在匹配过程中,主串指针i和模式串指针j会同时后移:- 若主串和模式串的字符相等,i和j同时后移一位。

- 若主串和模式串的字符不相等,则根据next数组的值,将模式串指针j回溯到合适的位置,继续匹配。

三、KMP算法的应用场景KMP算法在字符串匹配中有广泛的应用,特别是在大规模文本中的模式匹配问题上具有明显的优势。

以下是KMP算法的几个应用场景:1. 子串匹配:判断一个字符串是否是另一个字符串的子串。

KMP算法

KMP算法

KMP算法KMP算法是一种用于字符串匹配的快速算法,全称为Knuth-Morris-Pratt算法,是由Donald Knuth、Vaughan Pratt和James Morris在1977年共同提出的。

该算法的核心思想是通过利用已经匹配过的部分来避免不必要的字符比较,从而提高匹配效率。

1.暴力匹配算法在介绍KMP算法之前,我们先来了解一下暴力匹配算法。

暴力匹配算法,又称为朴素匹配算法,是最基本的匹配方法,它的思想就是从主串的第一个字符开始,逐个比较主串和模式串的字符,直到匹配成功或者主串和模式串的所有字符都比较完毕。

具体算法如下:```暴力匹配(主串S,模式串P):i=0j=0n = length(S)m = length(P)while i < n and j < m:if S[i] == P[j]: // 匹配成功,继续比较下一个字符i++else: // 匹配失败,模式串向后移动一位i=i-j+1j=0if j == m: // 匹配成功return i - jelse: // 匹配失败return -1```暴力匹配算法的时间复杂度为O(n*m),其中n和m分别为主串和模式串的长度。

2.KMP算法的思想KMP算法的关键在于构建一个部分匹配表,通过这个表来确定模式串在匹配失败时应该移动的位置。

部分匹配表的定义如下:对于模式串P的前缀子串P[0:i],如果存在一个真前缀等于真后缀,则称其长度为i的真前缀的真后缀长度为部分匹配值。

假设有一个模式串P,我们定义一个部分匹配表next,其中next[i]表示在P[i]之前的子串(不包括P[i])中,有多大长度的相同前缀后缀。

例如,P="ABCDABD",则next[7]=2,因为在P[7]之前的子串中,"ABD"是长度为3的前缀,也是长度为3的后缀。

构建部分匹配表的算法如下:构建部分匹配表(P):m = length(P)next = [0] * m // 初始化部分匹配表j=0k=-1next[0] = -1while j < m - 1:if k == -1 or P[j] == P[k]: // P[j]表示后缀的单个字符,P[k]表示前缀的单个字符j++k++next[j] = kelse:k = next[k]```构建部分匹配表的时间复杂度为O(m),其中m为模式串的长度。

kmp百度百科

kmp百度百科

kmp算法[编辑本段]kmp算法-概述一种改进的字符串匹配算法,由 D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。

[编辑本段]kmp算法-学习介绍完全掌握KMP算法思想学过数据结构的人,都对KMP算法印象颇深。

尤其是新手,更是难以理解其涵义,搞得一头雾水。

今天我们就来面对它,不将它彻底搞懂,誓不罢休。

如今,大伙基本上都用严蔚敏老师的书,那我就以此来讲解KMP 算法。

(小弟正在备战考研,为了节省时间,很多课本上的话我都在此省略了,以后一定补上。

)严老的《数据结构》79页讲了基本的匹配方法,这是基础。

先把这个搞懂了。

80页在讲KMP算法的开始先举了个例子,让我们对KMP的基本思想有了最初的认识。

目的在于指出“由此,在整个匹配的过程中,i指针没有回溯,”。

我们继续往下看:现在讨论一般情况。

假设主串:s: ‘s(1) s(2) s(3) ……s(n)’; 模式串:p: ‘p(1) p(2) p(3)…..p(m)’把课本上的这一段看完后,继续现在我们假设主串第i个字符与模式串的第j(j<=m)个字符‘失配’后,主串第i个字符与模式串的第k(k<j)个字符继续比较此时,s(i)≠p(j), 有主串:S(1)……s(i-j+1)……s(i-1) s(i) ………….|| (相配) || ≠(失配)匹配串:P(1) ……. p(j-1) p(j)由此,我们得到关系式‘p(1) p(2) p(3)…..p(j-1)’= ’s(i-j+1)……s(i-1)’由于s(i)≠p(j),接下来s(i)将与p(k)继续比较,则模式串中的前(k-1)个字符的子串必须满足下列关系式,并且不可能存在k’>k 满足下列关系式:(k<j),‘p(1) p(2) p(3)…..p(k-1)’= ’s(i-k+1)s(i-k+2)……s(i-1)’即:主串:S(1)……s(i-k +1) s(i-k +2) ……s(i-1) s(i) ………….|| (相配) || || ?(有待比较)匹配串:P(1) p(2) ……p(k-1) p(k)现在我们把前面总结的关系综合一下有:S(1)…s(i-j +1)…s(i-k +1) s(i-k +2) ……s(i-1) s(i) ……|| (相配) || || || ≠(失配)P(1) ……p(j-k+1) p(j-k+2) ….... p(j-1) p(j)|| (相配) || || ?(有待比较)P(1) p(2) ……. p(k-1) p(k)由上,我们得到关系:‘p(1) p(2) p(3)…..p(k-1)’= ’s(j-k+1)s(j-k+2)……s(j-1)’接下来看“反之,若模式串中存在满足式(4-4)。

kmp 时间复杂度计算

kmp 时间复杂度计算

kmp 时间复杂度计算摘要:一、KMP 算法简介1.KMP 算法的概念2.KMP 算法的原理3.KMP 算法的作用二、KMP 算法的时间复杂度分析1.KMP 算法的时间复杂度公式2.KMP 算法时间复杂度分析的过程3.KMP 算法相对于其他字符串匹配算法的优势三、KMP 算法在实际应用中的案例1.KMP 算法在文本处理中的应用2.KMP 算法在信息检索中的应用3.KMP 算法在自然语言处理中的应用正文:一、KMP 算法简介KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用于在一个主字符串中查找一个子字符串出现的位置。

该算法由Donald Knuth、Charles Morris 和Vaughan Pratt 于1977 年共同提出,其核心思想是利用子字符串的前缀与后缀信息来避免不必要的字符比较,从而提高匹配速度。

1.KMP 算法的概念:KMP 算法是一种滑动窗口法,通过构建一个“部分匹配表”(也称为“失效函数”或“next 数组”),实现字符串的高效匹配。

2.KMP 算法的原理:从主字符串的第一个字符开始,将其与子字符串的第一个字符进行比较。

若相等,继续比较后续字符;若不等,根据部分匹配表的值,将子字符串向右移动若干个字符,再次进行比较。

如此循环,直至找到匹配的子字符串或到达子字符串末尾。

3.KMP 算法的作用:KMP 算法可以在O(n) 的时间复杂度内完成主字符串与子字符串的匹配,其中n 为字符串的长度。

相较于O(n^2) 的暴力匹配算法,KMP 算法具有较高的效率。

二、KMP 算法的时间复杂度分析1.KMP 算法的时间复杂度公式:最优情况下,KMP 算法的时间复杂度为O(n),其中n 为字符串的长度。

最坏情况下,KMP 算法的时间复杂度为O(n^2),此时子字符串与主字符串的前缀完全相同。

2.KMP 算法时间复杂度分析的过程:分析KMP 算法的时间复杂度,需要考虑最优情况、最坏情况和平均情况。

KMP

KMP

C
P
就是找到使共同的子串C和D长度最大的k
P向后“滑动”
j-k+1 P
D
j-1 j
k-1k
我们若在Pk=next[j]中找不到Pk=Pj,那么我们该从哪里找呢? 不要去一个一个的循环地找了,有现成的信息可以使用。
C G
P
j-k+1 D F j-1 j P E k-1 k P P向后“滑动” k’-1 k’=next[k]
1 其他情况(没找到k,则j需要移动到初始位置1,让模式串第一个 字符与主串当前字符比较)(说明可以把模式串移动到最前面) 已知next[1]=0 设next[j]=k,则有
A B
A=B j-1 j
P
k-1 k
j-k+1
next[j]求法
已知next[1]=0 设next[j]=k,则有
A B
A=B j-1 j
P向后“滑动”
相对于书上的公式: A=B (4-2) B=C (4-3) =>A=C (4-4)
next[j]求法

next=
0 当j=1时 (如果和模式串第一个字符相同,那么i++,这时不 能滑动字符串了)
Max{k|1<k<j且’P1…Pk-1’=‘Pj-k+1…Pj-1’}当此集合不为空时。 (也就是说找到了满足条件的k)
C G
P
பைடு நூலகம்
j-k+1 D F j-1 j P E k-1 k P P向后“滑动” k’-1 k’=next[k]
现在已知C=D,但Pj!=Pk怎么办呢? 因为k’=next[k],则可知道 E=F F=G E=G
那么这个k’是不是紧次于k最大而满足条件的k呢?显然 因为E在D之中是最长子串,那么就必然是C中的最长子串,因为C=D 若此时Pk’仍不等于Pj那么将Pk”=next[k’]与Pj比较 依此类推,直到相等为止,则找到了符合条件的最大k 若Pk与Pj一直不等,那么比到最后一定会比到P1与Pj 若此时还不相等,说明没有符合条件的k,则 next[j+1]=next[1]+1=1

KMP算法(推导方法及模板)

KMP算法(推导方法及模板)

KMP算法(推导⽅法及模板)介绍克努斯-莫⾥斯-普拉特算法Knuth-Morris-Pratt(简称为KMP算法)可在⼀个主⽂本S内查找⼀个词W的出现位置。

此算法通过运⽤对这个词在不匹配时本⾝就包含⾜够的信息来确定下⼀个匹配将在哪⾥开始的发现,从⽽避免重新检查先前匹配的。

此算法可以在O(n+m)时间数量级上完成串的模式匹配操作,其改进在于:每当⼀趟匹配过程中出现字符⽐较不等时,不需回溯i的指针,⽽是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续进⾏⽐较。

kmp的核⼼之处在于next数组,⽽为了⽅便理解,我先介绍KMP的思想KMP匹配当开始匹配时,如果匹配过程中产⽣“失配”时,指针i(原串的下标)不变,指针j(模式串的下标)退回到next[j] 所指⽰的位置上重新进⾏⽐较,并且当指针j退回⾄零时,指针i和指针j需同时加⼀。

即主串的第i个字符和模式的第⼀个字符不等时,应从主串的第i+1个字符起重新进⾏匹配。

简单来说,就是两个串匹配,如果当前字符相等就⽐较两个字符串的下⼀个字符,如果当前匹配不相等时,就让j(待匹配串的下标)回到next[j] 的位置,因为我们已经知道next数组的作⽤是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离,如ababac与abac⽐较时i=4,j=4时不匹配,则利⽤next数组让j=2继续匹配⽽不⽤重新开始。

(⽬前先不⽤管next数组的值时如何得到的,只要明⽩它的作⽤即可,下⾯回介绍)所以我们可以写出kmp的代码int KMP(char str[],char pat[]){int lenstr=strlen(str);int lenpat=strlen(pat);int i=1,j=1;while(i<=lenstr){if(j==0 || str[i]==pat[j]) //匹配成功继续往后匹配++i,++j;elsej=next[j]; //否则根据next数组继续匹配if(j==lenpat) //说明匹配完成return 1;}return 0;}接下来就是关键的求next数组了next数组⾸先,next数组取决于模式串本⾝⽽与相匹配的主串⽆关,我们可以对其递推得到。

KMP算法中nextval的计算方法

KMP算法中nextval的计算方法

KMP算法中nextval的计算方法KMP算法中nextval的计算方法!KMP算法即Knuth-Morris-Pratt算法,是模式匹配的一种改进算法,因为是名字中三人同时发现的,所以称为KMP算法。

关于nextval数组的求法,可以参考一下思路int get_nextval(SString T,int &nextval[ ]){//求模式串T的next函数修正值并存入数组nextval。

i=1; nextval[1]=0; j=0;while(iif(j==0||T[i]==T[j]){ ++i;++j;if (T[i]!=T[j]) nextval[i]=j;else nextval[i]=nextval[j];}else j=nextval[j];}}//get_nextval根据这段程序来求nextval的值是可以方便计算出来,但如果是应付考研试题或者期末考试就有点麻烦了,下面的思路可以在任何时候帮助大家很方便地求解nextval,希望同学们认真阅读:首先看看next数组值的求解方法。

next值为0,第二位的next值为1,后面求解每一位的next值时,根据前一位进行比较。

首先将前一位与其next值对应的内容进行比较,如果相等,则该位的next值就是前一位的next值加上1;如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。

看起来很令人费解,利用上面的例子具体运算一遍。

1.前两位必定为0和1。

2.计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3.计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next值加上1。

KMP算法

KMP算法

KMP算法在传统的字符串匹配算法中,最常用的算法是朴素的模式匹配算法。

该算法的基本思想是:从主串的第一个字符开始,逐个字符地与模式串进行比较,如果发现不匹配的字符,则回溯到主串的下一个字符重新开始匹配。

这种算法的时间复杂度是O(m*n),其中m为主串的长度,n为模式串的长度。

在主串与模式串长度相等时,该算法的时间复杂度甚至会达到O(n^2)。

KMP算法的核心思想是利用模式串的信息,避免不必要的比较。

它通过预处理模式串,构建一个部分匹配表(prefix table),来提供匹配失败时的回溯位置。

这样,在匹配的过程中,只需要根据部分匹配表的内容来调整主串和模式串的位置即可。

这种优化使得KMP算法的时间复杂度降低到O(m+n)。

具体来说,KMP算法在预处理模式串时,对于模式串的每个前缀子串,求出其最长的相等的前缀和后缀的长度。

这个长度被称为部分匹配值。

例如,对于模式串"ababc",它的前缀子串有"","a","ab","aba",而其相等的后缀子串有"","c","bc","abc"。

其中,最长的相等的前缀和后缀的长度是2,因此,部分匹配值为2、在KMP算法中,这个信息会被存储在部分匹配表中,即prefix table。

当进行匹配时,如果发现匹配失败,那么根据部分匹配表中的值来进行回溯。

具体来说,如果当前字符匹配失败,那么将模式串向右移动的距离为:当前字符之前的最长相等前缀的长度-1、这样,就可以将模式串与主串对齐继续匹配。

1. 预处理模式串,求出部分匹配表(prefix table)。

2.根据部分匹配表,进行匹配操作。

3.如果匹配成功,返回匹配的位置;否则,返回匹配失败。

总之,KMP算法是一种高效的字符串匹配算法,通过预处理模式串,提供了匹配失败时的快速回溯位置。

kmp算法next原理

kmp算法next原理

kmp算法next原理
KMP算法,全称是Knuth-Morris-Pratt算法,是字符串匹配中一种高效率的算法。

该算法的核心是,利用已经匹配过的部分来减少比较次数。

具体实现是,当出现不匹配时,可以根据已经匹配的前缀和后缀的关系,避免重新匹配已经匹配过的字符,直接跳过这些字符,将模式串向后移动到下一个需要匹配的位置。

那么如何计算这个“已经匹配的前缀和后缀的关系”呢?这就需要用到next数组了。

next数组,本质上是一个数组,用于存储模式串的最长相同真前缀和真后缀的长度。

其中“真前缀”和“真后缀”,是指除了字符串本身的前缀和后缀,即不包含整个字符串的前缀和后缀。

通过预处理模式串生成next数组,我们就可以在匹配过程中根据已经匹配的前缀和后缀的长度,来跳过不必要的比较,从而达到优化匹配速度的目的。

以上就是KMP算法及其核心原理--next数组的简要介绍。

KMP算法(改进版)

KMP算法(改进版)

4.3.2 模式匹配的一种改进算法这种改进算法是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。

此算法可以在O(n+m)的时间数量级上完成串的模式匹配操作。

其改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。

下面先从具体例子看起。

↓ i=3第一趟匹配 a b a b c a b c a c b a ba b c↑ j=3↓ i━━━━→3第二趟匹配a b a b c a b c a c b a ba b c a c↑━━→↑ j=5j=1 ↓ i━→ i=11第三趟匹配a b a b c a b c a c b a b(a)b c a c↑━→j=6回顾4.3的匹配过程示例,在第三趟的匹配中,当i=7、j=5字符比较不等时,又从i=4、j=1重新开始比较。

然后,经仔细观察可发现,在i=4和j=1,i=5和j=1以及i=6和j=1这三次比较都是不必进行的。

因为从第三趟部分匹配的结果就可以得出,主串中第4、5和6个字符必然是‘b’、‘c’和‘a’(即模式串中第2、3和4个字符)。

因为模式中的第一个字符是a,因此它无需再和这三个字符进行比较,而仅需将模式向右滑动三个字符的位置继续进行比较i=7、j=2的字符比较即可。

同理,在第一趟匹配中出现字符不等时,仅需将模式向右滑动两个字符的位置继续进行i=3、j=1时的字符比较。

由此,在整个匹配的过程中,i指针没有回溯,如图4.4所示。

现在讨论一般情况。

假设主串位‘s1s2…s n’,模式串为‘p1p2…p m’,从上例的分析可知,为实现改进算法,需要解决下述问题:当匹配过程中产生“失配”(即s i≠p j)时,模式串“向右滑动”可行的距离有多远,换句话说,当主串中第i个字符与模式中第j个字符“失配”(即比较不等)时,主串中第i个字符(i指针不回溯)应与模式中哪个字符再比较?假设此时应与模式中第k(k<j)个字符继续比较,则模式中前k-1个字符的字串必须满足下列关系式(4-2),且不可能存在k’>k,满足下列关系式(4-2)‘p1p2…p k-1’=‘s i-k+1s i-k+2…s i-1’ (4-2)而已经得到的“部分匹配”的结果是‘p j-k+1p j-k+2…p j-1’=’s i-k+1s i-k+2…s i-1’ (4-3)由(4-2)和(4-3)推得下列等式‘p1p2…p k-1’=‘p j-k+1p j-k+2…p j-1’ (4-4)反之,若模式串中存在满足式(4-4)的两个字串,则当匹配过程中,主串中第i个字符与模式中第j个字符比较不等时,仅需将模式向右滑动至模式中第k个字符和主串中第i个字符对齐,此时,模式中头k-1个字符的字串’p1p2…p k-1’必定与主串中第i个字符之前长度为k-1的字串’s i-k+1s i-k+2…s i-1’相等,由此,匹配仅需从模式中第k个字符与主串中第i个字符比较起继续进行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

KMP算法是一种字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。

它的核心思想是利用已经匹配过的部分信息,尽量减少不必要的比较。

KMP算法的公式如下:
1. 预处理模式串,得到next数组:
-初始化next数组,next[0] = -1,next[1] = 0;
-从第2个字符开始,依次计算next[i]的值:
-如果模式串的前缀和后缀匹配,即pattern[j] == pattern[i-1],则next[i] = j + 1;
-如果模式串的前缀和后缀不匹配,即pattern[j] != pattern[i-1],则需要回溯到前一个可能的匹配位置,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;
-如果回溯到起始位置仍然没有找到匹配位置,则next[i] = 0。

2. 在主串中查找模式串:
-初始化主串指针i = 0,模式串指针j = 0;
-依次比较主串和模式串的字符:
-如果主串和模式串的字符匹配,即text[i] == pattern[j],则继续比较下一个字符;
-如果主串和模式串的字符不匹配,即text[i] != pattern[j],则需要根据next数组回溯模式串的指针j,即j = next[j],直到找到一个匹配位置或者回溯到起始位置;
-如果回溯到起始位置仍然没有找到匹配位置,则主串指针i和模式串指针j都向后移动一位,继续比较下一个字符;
-如果模式串指针j移动到模式串的末尾,则表示找到了一个匹配位置,返回匹配位置的起始索引;
-如果主串指针i移动到主串的末尾,则表示没有找到匹配位置,返回-1。

KMP算法通过预处理模式串得到next数组,利用next数组的信息在匹配过程中尽量减少不必要的比较,提高了匹配效率。

相关文档
最新文档