KMP算法详解(超级详细)

合集下载

MillerRabin算法和Las Vegas,Monte Carlo以及KMP算法

MillerRabin算法和Las Vegas,Monte Carlo以及KMP算法

{
lpx = lpx*2+x[i]-'0'; lpy = lpy*2+y[i]-'0';
lpx%=p;
lpy%=p;
} for (i=0;i<yl;i++)//计算 Wp
{
Wp*=2;
Wp%=p;
}
//Wp = expmod(2,yl,p);
for (int j=0;j<=xl-yl;j++) { if (lpx==lpy)//如果指纹相等
if(k == -1 || y[j] == y[k]) {
j++; k++; if(y[k] != y[j])
next[j] = k; else
next[j] = next[k];
//next[j] = k; } else
Monte Carlo (ms)
KMP (ms)
出错 个数 (个)
出错率
测试 对数 (对)
10
16
10
15
0 0.00% 5000
20
20
15
16
11 0.22% 5000
50 30
31
23
18
3 0.06% 5000
40
15
31
16
1 0.02% 5000
50
30
16
31
0 0.00% 5000
50
62
46
64
1 0.02% 5000
100
94
61
32
5 0.10% 5000
500 150
31
95

模式匹配算法及应用教案

模式匹配算法及应用教案

模式匹配算法及应用教案模式匹配算法是指在一个文本字符串中查找一个给定的模式(也称为目标字符串)的算法。

在计算机科学中,模式匹配是一个非常重要的问题,在许多应用领域都有广泛的应用,如字符串匹配、数据压缩、图像处理等。

一、模式匹配算法的分类1. 朴素模式匹配算法:朴素模式匹配算法(也称为暴力算法)是一种简单直观的模式匹配算法。

它的基本思想是从目标字符串的第一个字符开始,对比目标字符串和模式字符串的每个字符是否相等,如果不等,则向右移动目标字符串一个位置,再次开始对比;如果相等,则继续对比下一个字符,直到模式字符串的所有字符都匹配成功或目标字符串结束。

朴素模式匹配算法的时间复杂度为O(mn),其中m是目标字符串的长度,n 是模式字符串的长度。

2. KMP算法:KMP算法是一种高效的模式匹配算法,它的核心思想是通过利用已匹配部分的信息来避免不必要的对比。

具体来说,KMP算法通过构建一个"部分匹配表"(也称为next数组),来记录模式字符串中每个字符前面的最长匹配前缀和后缀的长度。

在匹配过程中,当出现不匹配的字符时,可以利用部分匹配表的信息来确定下一次对比的位置,从而实现跳跃式的移动。

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

3. Boyer-Moore算法:Boyer-Moore算法是一种基于字符比较的模式匹配算法,它的主要思想是从目标字符串的最末尾开始比较。

通过预先计算模式字符串中的每个字符在模式字符串中最右出现的位置,可以根据目标字符串中不匹配的字符在模式字符串中的位置进行跳跃移动,从而实现快速的匹配。

Boyer-Moore算法的时间复杂度平均情况下为O(n/m),其中n是目标字符串的长度,m是模式字符串的长度。

二、模式匹配算法的应用1. 字符串匹配:字符串匹配是模式匹配算法的最常见应用之一。

在很多应用中,需要在一个文本字符串中查找给定的子字符串。

BMY、KMP、BM、BMHS算法性能比较

BMY、KMP、BM、BMHS算法性能比较
int i, pos = 0;
for (pos = 1; pos <= len_s - len_d + 1;) {
num_bmhs++; for (i=pos+len_d-2; i>=pos-1 ; i--) {
if (src[i] == des[i-pos+1]) {
bidui_bmhs++; } else if (src[i] != des[i-pos+1]) {
void BuildGoodS(const char *pattern, size_t pattern_length, unsigned int* goods) {
unsigned int i, j, c; for(i = 0; i < pattern_length - 1; ++i) {
goods[i] = pattern_length; }
num_kmp++; //模式串和文本串从前向后匹配 while(i == -1 || s[j] == p[i])
{ i++; j++; bidui_kmp++;
if(i == plen) break;
} bidui_kmp++; //找到匹配的模式串 if(i == plen) {
res.push_back(j-i); j += 1; i = 0; match_kmp++; } //出现失配的情况 else {
for (int i=0; i<plen; i++) alphabet[des[i]] = plen - i - 1;

关键字匹配函数

关键字匹配函数

关键字匹配函数
在计算机科学中,关键字匹配函数通常用于在文本或数据集中查找特定的关键字或模式。

这些函数可以用于各种应用,如搜索引擎、数据挖掘、自然语言处理等。

以下是一些常见的关键字匹配函数的示例:
1.朴素字符串匹配(Naive String Matching):这是最简单的关键字匹配算法,它逐个比较文本中的每个字符与目标关键字。

时间复杂度为O(n),其中n是文本的长度。

2.KMP算法(Knuth-Morris-Pratt算法):KMP算法是一种改进的字符串匹配算法,它通过预处理目标关键字来减少比较次数。

时间复杂度为O(n+m),其中n是文本的长度,m是目标关键字的长度。

3.BM算法(Boyer-Moore算法):BM算法也是一种改进的字符串匹配算法,它通过构建坏字符规则和好后缀规则来减少比较次数。

时间复杂度为O(n+m)。

4.AC自动机(Aho-Corasick算法):AC自动机是一种多模式字符串匹配算法,它通过构建Trie树和失配指针来同时匹配多个关键字。

时间复杂度为O(m),其中m是关键字的数量。

5.KMP算法的变种:有一些基于KMP算法的变种,如Sunday算法、逆Sunday算法等,它们通过不同的方式来预处理目标关键字,以减少比较次数。

这些函数都有各自的优点和缺点,选择哪种函数取决于具体的应用场景和需求。

例如,对于小文本和短关键字,朴素字符串匹配可
能足够快;对于大文本和长关键字,KMP、BM或AC自动机可能更有效。

KMP(修改版)

KMP(修改版)
© Zachary Jia, 2015
11
部分匹配表的修正二(next数组):
© Zachary Jia, 2015
12
继续匹配:
j=3匹配失败,C对应的部分匹配值为0,已经匹配的 字符数为2,因此模式串右移两位。
j=1匹配失败,A对应的部分匹配值为-1,已经匹配 的字符数为0,因此字符串右移1位。
三、KMP(D.E.Knuth, V.R.Pratt, J.H.Morris) 算法
KMP算法的时间复杂度可以达到O(m+n)
其改进在于: 每当一趟匹配过程中出现字符比较不等时, 不需回溯 i 指针,而是利用已经得到的“部分 匹配”的结果将模式向右“滑动”尽可能远的 一段距离后,继续进行比较。
© Zhihai WANG, 2015
1
第一趟匹配:
第二趟匹配:
© Zachary Jia, 2015
2
第五趟匹配:
失配:
© Zachary Jia, 2015
3
暴力匹配的做法:
But… 很明显,这一步的匹配是没有必要进行的, 因为 肯定不可能匹配。这就造成了效率的降低。
© Zachary Jia, 2015
4
一个基本事实:
当空格与D不匹配时,你其实知道前面六个 字符是“ABCDAB”。也就是说,我们能够完 全可以利用这个已知信息,跳过某些不必要 的比较。
© Zachary Jia, 2015
15
Thank You!
© Zachary Jia, 2015
7
“部分匹配值”就是“前缀”和“后缀”的最长的共 有元素的长度。
© Zachary Jia, 2015
8
部分匹配表的用法:

字符串匹配问题的算法步骤

字符串匹配问题的算法步骤

字符串匹配问题的算法步骤字符串匹配是计算机科学中常见的问题,主要用于确定一个字符串是否包含另一个字符串。

解决这个问题的算法可以分为暴力匹配算法、Knuth-Morris-Pratt(KMP)算法和Boyer-Moore(BM)算法等。

暴力匹配算法是最简单的一种方法。

它的基本思想是从主串的第一个字符开始,依次和模式串的每个字符进行比较,直到找到一个字符不匹配为止。

如果找到了不匹配的字符,则将主串的指针后移一位,重新开始匹配。

如果匹配成功,模式串的指针向后移一位,主串的指针也向后移一位,继续匹配。

这个过程一直进行下去,直到模式串的指针到达模式串的末尾,或者找到了一个匹配的子串。

尽管暴力匹配算法很简单,但是它的时间复杂度较高,为O(m*n),其中m是主串的长度,n是模式串的长度。

当主串和模式串很长时,暴力匹配算法的效率就会很低。

为了提高字符串匹配的效率,有很多其他的算法被提出。

其中比较著名的是KMP算法和BM算法。

KMP算法的核心思想是,当发生不匹配的情况时,不需要回溯主串的指针,而是通过已经匹配的部分字符的信息,将模式串的指针移动到一个新的位置,从而避免了不必要的比较。

具体来说,KMP算法在匹配的过程中,通过建立一个部分匹配表(Partial Match Table),来记录模式串中每个位置的最长前缀后缀的长度。

当发生不匹配的情况时,根据部分匹配表的信息,可以将模式串的指针直接移动到下一个可能匹配的位置。

BM算法是一种基于启发式的匹配算法,它的核心思想是从模式串的尾部开始匹配,并根据已经匹配的部分字符的信息,跳跃式地移动模式串的指针。

具体来说,BM算法分别构建了坏字符规则和好后缀规则。

坏字符规则用于处理主串中与模式串不匹配的字符,找到最右边的该字符在模式串中的位置,并移动模式串的指针到对齐该字符。

好后缀规则用于处理主串中与模式串匹配的部分,找到最右边的该部分在模式串中的位置,并移动模式串的指针到对齐该部分。

扩展KMP算法


如何求解next[]数组 如何求解next[]数组 next[]
还剩下一个问题:next[]这个辅助数组怎 么计算?复杂度是多少? 我们发现计算next实际上以 为母串、T 实际上以T为母串 实际上以 为母串、 为子串的一个特殊“扩展的KMP”。用上 为子串的一个特殊“扩展的 ” 文介绍的完全相同的算法计算next即可。 (用next本身计算next,具体可以参考标准 KMP)此不赘述。
Thank you!
容易发现,如果有某个位置i满足 extend[i]=m,那么T就肯定在S中出现过, 并且进一步知道出现首位置是i——而这正 是经典的KMP问题。 因此可见“扩展的KMP问题”是对经典 KMP问题的一个扩充和加难。
例子 S=’aaaaaaaaaabaa a’, T=’aaaaaaaaaaa’。
比如ababab ,next[2] = 4, 2,3匹配0,1 ;然后4,5匹配2,3;相当 于还是匹配0,1 ;所以0,1被重复了3次, 所以只要是能匹配上的,就是在重复前i个 字符 ,能匹配多长,就是重复了多长,直 接用i+next[i]就是最长的长度 。
求解extend数组的模板
void GetExtand(const EleType str[], int strLen, int extand[], const EleType mode[], int modeLen, int next[]) { int i, a, p, j(-1); for (i = 0; i < strLen; ++i, --j) { if (j < 0 || i + next[i - a] >= p) { if (j < 0) j = 0, p = i; while (p < strLen && j < modeLen && str[p] == mode[j]) ++p, ++j; extand[i] = j, a = i; } else extand[i] = next[i - a]; } }

M P 算 法 和 O M P 算 法 及 其 思 想

KMP(MP)算法*(?▽?)?对方不想和你说话并且向你扔出了一个题。

【题目】 luogu 3375 KMP字符串匹配题目描述如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。

为了减少骗分的情况,接下来还要输出子串的前缀数组next。

(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。

)输入输出格式输入格式:第一行为一个字符串,即为s1(仅包含大写字母)第二行为一个字符串,即为s2(仅包含大写字母)输出格式:若干行,每行包含一个整数,表示s2在s1中出现的位置接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。

输入输出样例输入样例#1:输出样例#1:时空限制:1000ms,128M数据规模:设s1长度为N,s2长度为M对于30%的数据:N=15,M=5对于70%的数据:N=10000,M=100对于100%的数据:N=1000000,M=1000Ps:由于我打的字符串下标是以0为开头的,学的也是以0为开头的,将就看吧。

对于这个题,让我们先抛开kmp,想想可以怎么解_(:з」∠)_首先想到的是暴力匹配。

对于s1和s2,暴力枚举每一个点并进行匹配,由于每次进行匹配时时间复杂度为O(m),至少需要扫(n-m)个点,时间复杂度近似O(nm),TLE!优化:每次匹配时如果有不同的就直接跳过。

依旧会T…orz那么…(?▽?)? kmp…KMP算法简介kmp算法是一种改进的字符串匹配算法,由 D.E.Knuth,J.H.Morris 和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。

KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。

时间复杂度O(m+n)。

(摘自百度百科)O(m):对s2的预处理O(n):扫一遍s1,完成匹配当匹配的过程中发现s1[i]与s2[j]不同时如匹配到c和a发现他们不同:暴力会把aabaabaa往后移一位重新比较。

对称字符串算法

对称字符串算法对称字符串算法通常是指那些能够处理具有对称性质的字符串或序列的算法。

在计算机科学中,对称性可以出现在多种不同的上下文中,例如字符串匹配、加密算法、生物信息学中的序列比对等。

以下是一些常见的对称字符串算法:1. **KMP 算法(Knuth-Morris-Pratt)**:KMP 算法是一种高效的字符串匹配算法,它通过预处理模式串来创建一个部分匹配表(也称为失败函数),这样在不匹配时可以利用已匹配的部分信息,避免从头开始匹配,从而提高匹配效率。

KMP 算法本身不直接处理对称字符串,但其思想可以用于检测一个字符串是否是对称的。

2. **后缀数组和后缀树**:后缀数组和后缀树是处理字符串的对称性和周期性的数据结构。

它们可以用来快速找出字符串的所有后缀,并判断一个字符串是否具有对称性。

例如,如果一个字符串的所有后缀都是该字符串的前缀,则该字符串是对称的。

3. **回文数检测**:检测一个字符串是否为回文数(正读和反读都一样的字符串)是一个典型的对称字符串问题。

可以通过比较字符串与其反转字符串是否相等来解决。

这也可以通过反转字符串的一半并比较剩余的一半来实现,这样只需要遍历字符串一次。

4. **哈希算法**:一些哈希算法,如MD5,可能会产生对称的哈希值,即使输入字符串不是对称的。

这种性质有时被用于特定的密码学应用。

5. **编码和解码算法**:在加密学中,一些算法如凯撒密码的变种可以是对称的,即加密和解密使用相同的密钥和过程。

6. **生物信息学中的序列比对**:在生物信息学中,算法如BLAST可以用来自动化地检测两个序列之间的对称区域,这些区域可能表明序列之间的相似性或保守性。

在实现这些算法时,需要严格遵守相关领域的法律法规和伦理准则,确保算法应用的正确性和安全性。

特别是在加密学和生物信息学领域,算法的使用涉及到国家安全的敏感信息和生物伦理的考量。

在设计和应用这些算法时,应当确保符合国家的相关政策和规定。

数据结构教学中KMP算法解析

数据结构教学中KMP算法解析摘要:模式匹配是字符串的基本运算之一,也是数据结构教学中的难点之一。

分析了模式匹配KMP算法以及算法中next函数的含义,给出了next函数的两种实现方法,有助于在教学实践中帮助学生更好地理解该算法。

关键词:数据结构;模式匹配;KMP算法0引言模式匹配(Patten Matching)是许多计算机应用领域的基础问题,在数据结构中模式匹配是字符串的基本运算之一。

字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。

有两个字符串S和T,字符串S称为目标串,字符串T称为模式串,要求找出模式T在S中的首次出现的位置。

一旦模式T在目标S中找到,就称发生一次匹配。

有些应用可能会要求找出所有的匹配位置<sup>[1]</sup>。

例如,目标串S= 'Shanghai',模式串T= 'gha',则匹配结果为4。

模式匹配的典型算法包括朴素匹配算法、KMP算法和BM算法等,其中KMP算法是效率较高且经典的模式匹配算法之一<sup>[2]</sup>。

在数据结构教学中,由于KMP算法较难理解,课堂讲授往往很难取得好的效果。

本文通过对传统的朴素匹配算法与KMP算法的比较,分析next函数的含义以及实现方法,来帮助理解KMP算法。

1朴素匹配算法在朴素匹配算法中,S和T分别为目标串和模式串,变量i和j 为两个静态指针,分别表示S和T中当前正待比较的字符位置。

算法的基本思想是:第1趟匹配:从S的第1个字符(序号为0)起和T的第一个字符比较之,如果相等,则继续逐个比较后续字符(i++;j++),否则开始下一趟匹配。

新的一趟匹配:i的初值为上一趟的初值+1 ,j的初值为1,如果比较结果相等,则继续逐个比较后续字符,否则开始下一趟匹配。

依次类推,直至某一趟匹配中,T的每个字符依次和S中的一个连续的字符序列相等,则称匹配成功,否则称匹配不成功。

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

KMP算法详解(超级详细)
KMP算法,全称为Knuth-Morris-Pratt算法,是一种用于字符串匹
配的快速算法。

它的核心思想是在匹配过程中,当出现不匹配的情况时,
利用已经匹配的字符信息,避免进行重复匹配,从而提高匹配效率。

首先,我们需要了解一个重要的概念,"部分匹配值"(partial
match table),它指的是字符串的前缀和后缀的最长的共有元素的长度。

例如,在字符串"ABCDABD"中,它的部分匹配值是[0, 0, 0, 0, 1, 2, 0]。

接下来,我们来详细了解KMP算法的实现过程:
1.首先,针对模式串(被查找的字符串)进行预处理,得到部分匹配表。

-定义两个指针,i和j,分别指向模式串的开头和当前字符。

-初始化部分匹配表,将第一个元素置为0。

-在循环中,不断地根据当前指针所指向的字符,判断是否匹配。

-若匹配,则将部分匹配表的下一个元素置为当前指针位置的下一个
元素的值加1,并同时将当前指针和i都自增1
-若不匹配且i>0,则将i更新为部分匹配表的前一个元素的值。

-若不匹配且i=0,则将当前指针自增1
-循环结束后,部分匹配表得到构建。

2.匹配过程:
-定义两个指针,i和j,分别指向需要匹配的文本和模式串的开头。

-在循环中,不断地根据当前指针所指向的字符,判断是否匹配。

-若匹配,则将两个指针都自增1
-若不匹配且j>0,则将j更新为部分匹配表的前一个元素的值。

-若不匹配且j=0,则将当前指针自增1
-若模式串的指针j指向了最后一个字符,则说明匹配成功,返回匹配的位置。

-若循环结束仍未找到匹配的位置,则匹配失败。

总结一下,KMP算法可以分为两个步骤:预处理和匹配。

预处理的过程是构建部分匹配表,通过比较前缀和后缀的最长共有元素的长度,将这个长度记录在部分匹配表中。

匹配的过程是根据部分匹配表中的信息,来确定下一步的匹配位置,提高匹配的效率。

通过KMP算法,我们可以有效地解决字符串匹配问题,提高了匹配的效率。

它的核心思想是将已经匹配的字符信息保存起来,避免了对已经匹配过的字符的重复匹配,从而节省了时间。

相关文档
最新文档