(Rabin-Karp算法)匹配字符串(滚动哈希)

简介: Rabin-Karp 算法用于多模式搜索,常用于重复检测和生物信息学中寻找两个或多个蛋白质的相似性。

(Rabin-Karp算法)匹配字符串(滚动哈希)


Rabin-Karp算法的思路是将字符串的比较转换成数字的比较。比较两个长度为m的字符串是否相等需要O(m)的时间,而比较两个数字是否相等通常可以是O(1)。为了将字符串映射到对应的数字,故此需要用到哈希函数。


接下来的问题是,如何快速将字符串映射到对应的数字呢?如果需要在 O(L)的时间内算出编码,这种方法就没有意义了,因为这个直接进行字符串比较需要的时间相同。为了能够快速计算出字符串编码,我们可以将字符串看成一个 26 进制的数(因为字符串中仅包含26个字母),它对应的 10 进制的值就是字符串的编码值。

首先将字符转换为 26 进制中的 0-25,即通过 arr[i] = (int)S.charAt(i) - (int)'a',可以将字符串 abcd 转换为 [0, 1, 2, 3],它对应的 10 进制值为:
在这里插入图片描述
我们将这个表达式写得更通用一些,设 c[i]为字符串中第 i 个字符对应的数字,a = 26为字符串的进制,那么有:
在这里插入图片描述


Rabin-Karp 算法用于多模式搜索,常用于重复检测和生物信息学中寻找两个或多个蛋白质的相似性。例如,判断一个字符串中是否有重复的字符串出现或者一个字符串中是否包含另一个字符串就可以用Rabin-Karp 算法。

例如:
判断s="abcdefghijkl"是否包含"bcde"子串?

利用上面公式先计算出"bcde"的哈希编码,然后开始在字符串s中找,首先将字符转换为 26 进制中的 0-25,即通过 arr[i] = (int)S.charAt(i) - (int)‘a’,可以将字符串 abcd 转换为 [0, 1, 2, 3],向右移动滑动窗口,从 abcd 变成 bcde,此时字符串对应的值从 [0, 1, 2, 3] 变成 [1, 2, 3, 4],移除了最高位的 0,并且在最低位添加了 4,那么我们可以快速地计算出新的字符串的编码:

在这里插入图片描述

更通用的写法是:

在这里插入图片描述

这样,我们只需要 O(L)的时间复杂度计算出最左侧子串的编码(即滑动窗口起始的编码),这个O(L) 和滑动窗口的循环是独立的。在滑动窗口向右滑动时,计算新的子串的编码的时间复杂度仅为 O(1)。


在实际的编码计算中,h0和h1的值可能会非常大,在 Java 语言中,会导致整数的上溢出。一般的解决方法时,对编码值进行取模,将编码控制在一定的范围内,防止溢出,即h = h % modulus。
h0对应的java代码为:

hash = ((hash * g) % MOD + arr[i]) % MOD;  //g可以理解为进制,本题中是26

h1对应的java代码为:

 hash = ((hash - arr[i - a] * Math.pow(g, a - 1) % MOD + MOD) % MOD * g % MOD + arr[i]) % MOD;  
 //a为滑动窗口的大小,需要匹配的字符串的长度


Rabin-Karp算法的优势

Rabin-Karp算法的优势是可以多维度或者多模式的匹配字符串。以多模式匹配为例,如果需要在文本T中找出模式集合P=[P1, P2, ...Pk]中所有出现的模式。对于这个问题,Rabin-Karp算法的威力就能发挥出来了,Rabin-Karp算法能通过简单地扩展便能够支持多模式的匹配。

算法本质:按照k进制,进行编码,数据太多了,就取模。实际应用中因为无法确定起始字符串的长度,常常与二分一起使用。

看完之后大家可以用这个题练习一下:[leetcode 1044. 最长重复子串[困难]](https://leetcode-cn.com/problems/longest-duplicate-substring/)

目录
相关文章
|
3月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
67 3
|
1月前
|
算法 安全
散列值使用相同的哈希算法
当使用相同的哈希算法对相同的数据进行散列时,所产生的散列值(也称为哈希值或摘要)总是相同的。这是因为哈希算法是一种确定性的函数,它对于给定的输入将始终产生相同的输出。 例如,如果你用SHA-256算法对字符串"hello world"进行哈希处理,无论何时何地,只要输入是完全一样的字符串,你都会得到相同的160位(40个十六进制字符)的SHA-256散列值。 但是,需要注意的是,即使是输入数据的微小变化也会导致产生的散列值完全不同。此外,不同的哈希算法(如MD5、SHA-1、SHA-256等)会对相同的数据产生不同的散列值。 哈希算法的一个关键特性是它们的“雪崩效应”,即输入中的一点小小
36 4
|
5月前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
3月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
112 1
两个字符串匹配出最长公共子序列算法
|
3月前
|
存储 算法 C#
C#哈希查找算法
C#哈希查找算法
|
3月前
|
算法 安全 Go
Python与Go语言中的哈希算法实现及对比分析
Python与Go语言中的哈希算法实现及对比分析
56 0
|
3月前
|
存储 算法 C++
【算法】哈希映射(C/C++)
【算法】哈希映射(C/C++)
|
5月前
|
算法 安全 JavaScript
安全哈希算法:SHA算法
安全哈希算法:SHA算法
116 1
安全哈希算法:SHA算法
|
5月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
5月前
|
JavaScript 算法 前端开发
国标哈希算法基础:SHA1、SHA256、SHA512、MD5 和 HMAC,Python和JS实现、加盐、算法魔改
国标哈希算法基础:SHA1、SHA256、SHA512、MD5 和 HMAC,Python和JS实现、加盐、算法魔改
699 1

热门文章

最新文章

下一篇
开通oss服务