作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
KMP算法是一种用于字符串搜索的高效算法,全称为Knuth-Morris-Pratt算法。它通过避免字符串的重复比较,提高搜索效率。KMP算法的核心是“部分匹配”表(也称为“最长公共前后缀”表),这个表用于在搜索过程中确定当发生不匹配时,模式串应该向右滑动多少位。
KMP算法的基本步骤如下:
构建部分匹配表(Next数组):对于模式串,计算每个位置之前字符串的最长公共前后缀长度。这个表用于在不匹配时决定模式串的滑动距离。
模式串与主串的匹配:使用Next数组,当模式串与主串在某个位置不匹配时,根据Next数组中的值,将模式串向右滑动相应的位数,而不是重新开始比较。
重复匹配过程:继续匹配过程,直到模式串与主串完全匹配,或者模式串滑过主串的末尾。
KMP算法的时间复杂度为O(n+m),其中n是主串的长度,m是模式串的长度,求next数组时间复杂度O(m)。这比朴素的字符串搜索算法(时间复杂度为O(n*m))要高效得多。
KMP算法的关键在于如何利用已匹配的信息,避免重复匹配。我将以一个简单的例子来解释KMP算法的工作原理。
假设我们有一个主串S
和一个模式串P
。我们想要找出P
在S
中的位置。如果用传统的暴力匹配方法,当S
和P
在某个位置不匹配时,我们会将P
向右移动一位,然后重新开始匹配。但KMP算法会这样做:
构建Next数组:首先,我们需要为模式串P
构建一个Next数组。这个数组的作用是,当P
与S
在某个位置不匹配时,告诉P
应该向右移动多少位。Next数组的每个元素Next[i]
表示P
的前i
个字符中,最长公共前后缀的长度。
例如,对于模式串P = "ABCDABD"
,Next数组如下:
Next[0] = 0
,因为没有任何字符。Next[1] = 0
,因为只有一个字符,没有前后缀。Next[2] = 0
,前两个字符"AB"没有公共前后缀。Next[3] = 0
,前三个字符"ABC"没有公共前后缀。Next[4] = 1
,前四个字符"ABCD"的公共前后缀是"A"。Next[5] = 2
,前五个字符"ABCDA"的公共前后缀是"AB"。Next[6] = 0
,前六个字符"ABCDAB"没有除了靠前个字符"A"之外的公共前后缀。Next[7] = 1
,前七个字符"ABCDABD"的公共前后缀是"A"。开始匹配:现在我们用模式串P
去匹配主串S
。
Next
数组。假设当前匹配到了模式串的第i
个字符失败,那么我们将模式串向右移动Next[i-1]
个位置,然后继续匹配。重复匹配过程:我们继续这个过程,直到模式串与主串完全匹配,或者模式串滑过主串的末尾。
通过这种方式,KMP算法避免了大量的重复匹配,大大提高了搜索效率。
寻找最长公共前后缀是KMP算法中的一个关键步骤。这个步骤通常在构建Next数组时完成。Next数组中的每个元素Next[i]
表示模式串P
的前i
个字符中,最长公共前后缀的长度。下面是寻找最长公共前后缀的步骤:
初始化:首先,我们需要初始化Next数组。通常,Next[0]
和Next[1]
都是0,因为一个字符或没有字符的情况下,不存在公共前后缀。
遍历模式串:从模式串的第二个字符开始,逐个字符向后遍历。
比较前后缀:对于当前字符P[i]
,我们需要比较它的前缀P[0...i-1]
和后缀P[1...i]
。这里的关键是利用已经计算出的Next
数组中的信息。
更新Next数组:如果P[i]
与P[Next[i-1]]
相等,那么Next[i] = Next[i-1] + 1
。这是因为如果当前字符与它之前的子串的最长公共前后缀的下一个字符相等,那么当前子串的最长公共前后缀就是之前子串的最长公共前后缀加上这个字符。
处理不匹配情况:如果P[i]
与P[Next[i-1]]
不相等,我们需要继续向前查找,直到找到一个位置j
,使得P[i]
与P[Next[j-1]]
相等,或者我们回到了模式串的起始位置。在这个过程中,我们实际上是在寻找当前字符之前的最长公共前后缀的次长公共前后缀。
重复上述过程:对于模式串中的每个字符,重复上述步骤,直到遍历完整个模式串。
通过这个过程,我们可以为模式串构建出Next数组,这个数组将在KMP算法的匹配阶段被用来决定模式串在不匹配时应该向右滑动多少位。
int Index_KMP(SString S, SString T, int next[]) { int i = 1, j = 1; // 初始化主串S和模式串T的指针i和j,从靠前个字符开始比较 while (i <= S.length && j <= T.length){ // 当两个指针都没有超出各自字符串的长度时,继续循环 if (j == 0 || S.ch[i] == T.ch[j]) { // 如果模式串的指针j已经移到靠前个字符,或者当前比较的字符相等 ++i; ++j; // 主串和模式串的指针都向后移动一位,继续比较下一个字符 } else j = next[j]; // 如果字符不匹配,根据next数组移动模式串的指针 // 这里的next[j]表示模式串中前j个字符的最长公共前后缀的长度 // 通过移动模式串,我们避免了不必要的重复比较 } if (j > T.length) return i - T.length; // 如果模式串的指针j超出了模式串的长度,说明匹配成功 // 返回匹配开始的位置,即主串指针i减去模式串长度T.length else return 0; // 如果模式串没有完全匹配,返回0表示匹配失败 }
TAG:kmp算法
标签: 当前位置: 首页 > 问答
相关文章
作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
说起建设网站,不得不提的就是网站绑定的域名,域名作为网站的门牌号,不仅仅要代表网站和企业的形象,更加要让访问者用起来方便快捷。小编就教大家如何为网站注...
2024-11-18 6
做一名企业家是多么匆忙啊! 从零开始创业是一件伤脑筋又有挑战性的事情,但同时也是一件非常有益且令人兴奋的事情。当您创立起您自己的事业,您将充满营销、...
2024-11-18 8
其实很多朋友们认为,注册域名的时候就需要选择自己喜欢的域名在进行注册,但是小编表示这样其实是不对的,域名注册则是被分为域名和域名交易平台两个部分,今天...
2024-11-18 7
我们在建造一个网站前,都会首先先思考挑选一个实用、好记的域名。可是实事是当咱们在查询域名时都会发现,有意义的域名,简直都被抢注一空。这时咱们就要改变一...
2024-11-17 7
作为中国最早的域名投资者之一,58同城的创始人姚劲波很早就把赶集网的同音域名ganjinwang.com收归旗下,现在打开该网址,仍然链接到58同城。...
2024-11-17 8
想必每一个做网站的朋友在注册域名的时候都是费尽脑汁的,好不容易想好了一个域名却发现已经被注册了,这个时候有一个批量域名查询工具是不是很方便,今天小编就...
2024-11-17 9