- karp算法gydF4y2Ba
的gydF4y2Ba- karpgydF4y2Ba算法是一个gydF4y2Ba字符串gydF4y2Ba-搜索算法,使用gydF4y2Ba哈希gydF4y2Ba在字符串中寻找模式。字符串是gydF4y2Ba抽象数据类型gydF4y2Ba它由一系列字符组成。字母、单词、句子等都可以表示为字符串。gydF4y2Ba
字符串匹配是计算机科学的一个非常重要的应用。如果您曾经在文档中搜索过某个特定的单词,那么您已经受益于字符串匹配技术。字符串匹配也可以通过比较文档中的字符串来检测抄袭gydF4y2Ba 文档中的字符串gydF4y2Ba .gydF4y2Ba
下面是Python中字符串的例子:gydF4y2Ba
1 2 3gydF4y2Ba |
|
内容gydF4y2Ba
天真的字符串匹配gydF4y2Ba
说有一个字的长度gydF4y2Ba 还有一份篇幅很长的文件gydF4y2Ba .单词和文档都表示为字符串。在文档中搜索单词的简单方法是从文档的开头开始并检查每一个gydF4y2Ba 按字母顺序,看它是否与单词中的字母匹配。如果gydF4y2Ba 文档的字母切片与gydF4y2Ba 单词里的字母,那么就找到了匹配。这是字符串检查的一种强制方法,在它运行之后,它肯定会输出正确的答案(无论单词是否在文档中)。然而,这个算法需要gydF4y2Ba 在最坏的情况下,需要时间来完成,因为对于文档中的几乎所有位置,算法都会执行gydF4y2Ba 比较以检查是否匹配。如果gydF4y2Ba 非常大gydF4y2Ba ,则算法取gydF4y2Ba 时间来完成。这非常慢。gydF4y2Ba
假设你想在一个DNA序列中搜索含有三个碱基的特定序列ATA。下面是一个动画,描述了使用朴素字符串匹配算法的搜索。gydF4y2Ba
下面是上面描述的蛮力字符串搜索算法的Python实现:gydF4y2Ba
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25gydF4y2Ba |
|
想象一下,搜索一个由10亿个“ACC”段和一个“ATA”段组成的字符串。的最坏情况运行时间将在此字符串中搜索“ATA”gydF4y2Ba .gydF4y2Ba
让这种蛮力算法变得更聪明、更高效的一个方法是减少不必要的比较。例如,如果我们正在寻找的字符串是“GAC”,而我们正在与它进行比较的段是“TCG”,那么在G和T之间的第一次比较之后,我们知道这将是不匹配的。因此,我们可以继续阅读文本的下一部分,而不必浪费时间比较序列中剩下的两个字母,因为我们知道它们肯定不匹配。gydF4y2Ba
如果我们要实现上面描述的优化,在检查单词长度时,算法的最佳运行时间是多少gydF4y2Ba 在篇幅较长的文本中gydF4y2Ba 如果算法发现这个词gydF4y2Ba不gydF4y2Ba出现在文本中?gydF4y2Ba
首先,让我们确定最佳情况——比较最少的情况。如果文本序列的第一个字母与单词的第一个字母不匹配,我们将进行最少的比较。在这种情况下,我们将执行gydF4y2Ba 比较,所以最佳情况下的运行时间是gydF4y2Ba .gydF4y2Ba
- karp算法gydF4y2Ba
Rabin-Karp算法利用gydF4y2Ba哈希函数gydF4y2Ba和gydF4y2Ba滚散列gydF4y2Ba技术。哈希函数本质上是一个将一个东西映射到一个值的函数。特别是,哈希可以将任意大小的数据映射到固定大小的值。gydF4y2Ba[1]gydF4y2Ba
哈希gydF4y2Ba
以下是关于哈希的速成课程:gydF4y2Ba
哈希是一种使用哈希函数将输入映射到输出来关联值的方法。散列的目的是获取一大块数据,并能够用更小的形式表示。哈希非常有用,但也有一些缺点,即碰撞。的gydF4y2Ba鸽子洞原理gydF4y2Ba告诉我们不能放gydF4y2Ba 球进gydF4y2Ba 没有至少一个装两个球的桶。通过哈希,我们可以将函数的输入看作球,桶看作函数的输出—一些输入必须不可避免地共享一个输出值,这称为冲突。gydF4y2Ba
滚动哈希允许算法计算哈希值,而不必重新哈希整个字符串。例如,当在文本中搜索一个单词时,当算法向右移动一个字母(就像在动画中的暴力),当从文本[0:2]移动时,算法不必计算文本[1:3]部分的哈希,而是可以使用滚动哈希对哈希进行操作,从旧的哈希得到新的哈希。gydF4y2Ba
假设你有一个哈希函数,它将字母表中的每个字母映射到一个唯一的质数,gydF4y2Ba .你正在搜索一篇文章gydF4y2Ba 的长度gydF4y2Ba 为一个字gydF4y2Ba 的长度gydF4y2Ba .假设文本是下面的字符串“abcdefghijklmnopqrstuvwxyz”,单词是“fgh”。我们如何使用滚动散列来搜索“fgh”?gydF4y2Ba
在每一步中,我们将文本的三个字母与单词的三个字母进行比较。第一步,我们可以乘法gydF4y2Ba 获取字符串" abc "的哈希值。类似地,“fgh”的哈希值为gydF4y2Ba .比较“abc”和“fgh”的哈希值,看看数字是否匹配。gydF4y2Ba
为了进入下一个迭代,我们需要计算“bcd”的散列值。我们怎么做呢?我们可以计算gydF4y2Ba ,但我们实际上是在重复我们已经做过的工作!gydF4y2Ba
我们知道gydF4y2Ba 我们知道gydF4y2Ba .如果我们把gydF4y2Ba 然后乘以gydF4y2Ba 我们可以得到“bcd”的哈希值。我们将这个值与“fgh”进行比较,以此类推。gydF4y2Ba
Rabin-Karp在滚动哈希实现中只使用简单的乘法和加法。gydF4y2Ba
所有的运算都是对质数取模完成的gydF4y2Ba 避免处理大量的数据。为了可读性和简单性,模gydF4y2Ba 已被排除,但当模gydF4y2Ba 是礼物。gydF4y2Ba
拉宾-卡普滚动哈希gydF4y2Ba[2]gydF4y2Ba
是一个常数,gydF4y2Ba 输入字符是,和gydF4y2Ba 要比较的字符串中有多少个字符(这是单词的长度)。gydF4y2Ba
让我们用Rabin-Karp的滚动哈希来哈希字母表。在这里,gydF4y2Ba 将gydF4y2Ba ,gydF4y2Ba 将gydF4y2Ba ,gydF4y2Ba 将表示字符在字母表中出现的位置—因此对于" a "gydF4y2Ba 将gydF4y2Ba ,对于“z”gydF4y2Ba 将gydF4y2Ba .gydF4y2Ba
让我们找到“abc”的哈希值,并用它来找到“bcd”的哈希值:gydF4y2Ba
为了得到“bcd”的散列,我们需要删除“a”并添加“d”:gydF4y2Ba
我们需要相乘gydF4y2Ba 通过gydF4y2Ba 因为我们要减去gydF4y2Ba 现在和" a "相关的术语现在需要和" b "相关。这会将值向左移动,这样d就会有gydF4y2Ba 系数:gydF4y2Ba
每一步都有固定数量的运算(一次减法,一次乘法,一次加法),这些运算都在固定时间内完成,gydF4y2Ba .当检查文本的子字符串是否等于单词时,算法只需要查看哈希值是否相等。这也可以在常数时间内完成。因为算法会执行gydF4y2Ba 操作在文字的每一个字符上都有gydF4y2Ba 文字中的字符,这一步需要gydF4y2Ba 时间。gydF4y2Ba
实施- karpgydF4y2Ba
下面是在Python中实现Rabin-Karp算法的一种方法gydF4y2Ba[3]gydF4y2Ba.gydF4y2Ba
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48gydF4y2Ba |
|
- karp的复杂性gydF4y2Ba
假设文本是长度gydF4y2Ba 这个单词的长度是gydF4y2Ba .Rabin-Karp的最佳和平均情况运行时间为gydF4y2Ba 因为滚动哈希步骤需要gydF4y2Ba 一旦算法找到一个潜在的匹配,它必须验证每个字母,以确保匹配是真实的,而不是哈希冲突的结果,因此必须检查每个gydF4y2Ba 单词中的字母。gydF4y2Ba
Rabin-Karp的最坏情况运行时间是gydF4y2Ba .这种情况会发生在一个非常糟糕的哈希函数中,导致每一步都出现假阳性。因为每当算法认为它找到了匹配,它必须验证每一个gydF4y2Ba 单词中的字母,如果每一步都有碰撞,gydF4y2Ba 信件会被检查gydF4y2Ba 导致运行时间为的gydF4y2Ba .这可以通过选择一个好的哈希函数来避免。gydF4y2Ba
在搜索要在文本中匹配的单个模式时,gydF4y2BaKnuth-Morris-Pratt算法gydF4y2Ba将是一个更快的选择。为了匹配多个模式,Rabin-Karp算法与一个gydF4y2Ba布隆过滤器gydF4y2Ba可以有效地找到文本中的多个模式。gydF4y2Ba[4]gydF4y2Ba
另请参阅gydF4y2Ba
参考文献gydF4y2Ba
- ,。gydF4y2Ba哈希函数gydF4y2Ba.检索于2016年5月28日gydF4y2Bahttps://en.wikipedia.org/wiki/Hash_functiongydF4y2Ba
- ,。gydF4y2Ba滚散列gydF4y2Ba.检索于2016年5月28日gydF4y2Bahttps://en.wikipedia.org/wiki/Rolling_hashgydF4y2Ba
- , m。gydF4y2Ba- karpgydF4y2Ba.检索于2016年5月28日gydF4y2Bahttps://github.com/mccricardo/Rabin-Karp/blob/master/rabin_karp.pygydF4y2Ba
- ,。gydF4y2Ba- karp算法gydF4y2Ba.检索于2016年5月29日gydF4y2Bahttps://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithmgydF4y2Ba