【算法】Rabin-Karp 算法

news2025/3/7 8:17:57

目录

  • 1.概述
  • 2.代码实现
  • 3.应用

更多数据结构与算法的相关知识可以查看数据结构与算法这一专栏。

有关字符串模式匹配的其它算法:
【算法】Brute-Force 算法
【算法】KMP 算法

1.概述

(1)Rabin-Karp 算法是由 Richard M. Karp 和 Michael O. Rabin 于 1987 提出的字符串匹配算法,它的基本思想是利用哈希函数对字符串进行编码,通过比较哈希码来判断是否可能发生匹配,并在发生哈希碰撞时进一步验证字符串是否匹配

(2)Rabin-Karp 算法的步骤如下:

  • ① 计算模式字符串的哈希码。
  • ② 计算目标串中同样长度的窗口字符串的哈希码。
  • ③ 比较窗口字符串的哈希码和模式字符串的哈希码:
    • 如果哈希码相同,进行进一步比较确认是否匹配。
    • 如果哈希码不同,移动窗口到下一个位置,通过哈希码滑动更新窗口的哈希码。
  • ④ 重复步骤 ③,直到找到匹配或遍历完整个文本字符串。

Rabin-Karp 算法的关键点是哈希函数的选择和哈希码的比较。一个好的哈希函数应该能够实现高效计算和压缩成较小的哈希码,以提高算法的效率。而比较哈希码可能会产生哈希碰撞,即不同字符串具有相同的哈希码。当发生哈希碰撞时,需要通过进一步的比较来确定字符串是否匹配。

(3)在Rabin-Karp算法中,计算字符串的哈希值通常采用的方式是基于进制转换的方法。具体而言,我们可以使用多项式哈希 (polynomial hashing) 来计算字符串的哈希值。考虑一个字符串 s,其中包含 n 个字符,字符的 ASCII 值分别为 c1, c2, …, cn。我们选择一个适当的基数,通常是 ASCII 表的大小,这里假设为 256。我们还选择一个素数,通常是 Rabin-Karp 算法的参数,这里假设为 101。那么,字符串 s 的哈希值 H(s) 计算方式如下:

H ( s ) = ( ( c 1 × p ( n − 1 ) ) + ( c 2 × p ( n − 2 ) ) + . . . + ( c n × p 0 ) )   %   M H(s) = ((c_1 × p^{(n-1)}) + (c_2 × p^{(n-2)}) + ... + (c_n × p^0)) ~ \% ~ M H(s)=((c1×p(n1))+(c2×p(n2))+...+(cn×p0)) % M

其中,p 表示进制数(这里是 256),n 表示字符串的长度,M 表示选择的素数(这里是 101)。例如,模式字符串 “ABAB” 的哈希值为 ((65 × 2563) + (66 × 2562) + (65 × 2561) + (66 × 2560)) % 101 = 13。

通过将字符的 ASCII 值乘以进制数的幂次方,并对结果进行求和,再对素数 M 取模,即可得到字符串的哈希值。这种计算方法具有较好的散列性质,可以在较小的哈希空间中尽可能地减少碰撞的发生。

(4)让我们通过一个例子来说明 Rabin-Karp 算法的工作过程。首先,假设我们有以下文本和模式字符串:文本串 “ABABABABC” 以及模式串 “ABAB”。此外,我们选择基数为 256,素数为 101 作为算法的参数。

  • 首先,我们计算模式字符串 “ABAB” 的哈希值为 13。
  • 接下来,我们计算文本中第一个与模式字符串等长的子串 “ABAB” 的哈希值。它的哈希值也为 13。
  • 由于哈希值相等,我们需要进行进一步的检查。我们比较模式字符串 “ABAB” 和文本中的子串 “ABAB” 字符串是否完全匹配。在此例中,它们是完全匹配的。
  • 如果我们没有找到匹配,我们需要通过滑动窗口的方式来更新子串的哈希值。在这种情况下,我们将滑动窗口向右移动一个位置,得到下一个子串 “BABA” 的哈希值。
  • 我们重复这些步骤,直到找到所有匹配的位置。

(5)上面需要注意的是,我们可以通过当前窗口字符串 “ABAB” 的哈希值来直接计算下一个窗口字符串 “BABA” 的哈希值,从而避免再次遍历 “BABA” 来计算其哈希值,提高了效率。我们以下图(来自《算法导论》)来说明:

在这里插入图片描述

为了方便说明,我们可以将字符串看作对应的数字字符串,再上图中,我们可以快速通过哈希值 31415 来计算下一个窗口的哈希值 14152(取模之后再计算也是一样的效果)。其主要思想在于 31415 的低 4 位与 14152 的高 4 位相同,并且我们知道 31415 的最高位与 14152 的最低位哦,因此只需要简单的数学计算便可以得到下一个窗口字符串的哈希值,从而保证在常数时间内更新下一个窗口字符串的哈希值。

2.代码实现

(1)Rabin-Karp 算法的代码实现如下:

class RabinKarpAlgorithm {

    //用于取哈希值时的除法因子
    private static final int PRIME = 101;
    //字符集的大小
    private static final int RADIX = 256;

    /*
    * s: 目标串
    * t: 模式串
    * 返回值: 模式串在目标串中所有匹配成功的位置
    * */
    public List<Integer> rabinKarp(String s, String t) {
        List<Integer> indices = new ArrayList<>();

        int sLen = s.length();
        int tLen = t.length();

        int h = 1;
        for (int i = 0; i < tLen - 1; i++) {
            h = (h * RADIX) % PRIME;
        }

        //初始化窗口内字符串和模式串的哈希值
        int sHash = 0;
        int tHash = 0;
        for (int i = 0; i < tLen; i++) {
            sHash = (sHash * RADIX + s.charAt(i)) % PRIME;
            tHash = (tHash * RADIX + t.charAt(i)) % PRIME;
        }

        for (int i = 0; i <= sLen - tLen; i++) {
            //当前窗口中字符串的哈希码与模式串的哈希码相同
            if (sHash == tHash) {
                //检查窗口中字符串 s[i...i + tLen - 1] 是否与模式串 t 相等
                int j;
                for (j = 0; j < tLen; j++) {
                    if (s.charAt(i + j) != t.charAt(j)) {
                        break;
                    }
                }
                if (j == tLen) {
                    //匹配成功
                    indices.add(i);
                }
            }
            if (i == sLen - tLen) {
                return indices;
            }
            //更新窗口中字符串的哈希值
            sHash = ((sHash - s.charAt(i) * h) * RADIX + s.charAt(i + tLen)) % PRIME;
            if (sHash < 0) {
                sHash += PRIME;
            }
        }
        return indices;
    }
}

(2)上述代码的测试如下:

class Test {
    public static void main(String[] args) {
        RabinKarpAlgorithm rabinKarpAlgorithm = new RabinKarpAlgorithm();
        String s = "cvbzxcvbnmacvb";
        String t = "cvb";
        List<Integer> indices = rabinKarpAlgorithm.rabinKarp(s, t);
        System.out.println(indices);
    }
}

输出结果如下:

[0, 5, 11]

3.应用

(1)Rabin-Karp 算法是一种常用的字符串匹配算法,适用于以下几个应用场景:

  • 字符串匹配:Rabin-Karp 算法可以用于在一个长文本串中高效地查找一个模式串的出现位置。它通过使用哈希函数和滚动哈希的技巧,在线性时间内完成匹配操作。
  • 模式匹配:Rabin-Karp 算法可用于检测一个文本串中是否包含指定的模式串。这在文本搜索、文件内容查找等应用中非常有用。
  • 字符串去重:Rabin-Karp 算法可以用于快速识别和去重重复的子串。通过计算子串的哈希值,并使用哈希表或哈希集合来记录已经出现的子串,可以高效地实现字符串去重的功能。
  • 数据校验:Rabin-Karp 算法可以用于快速计算数据块的哈希值,可以在数据传输或存储过程中用来验证数据的完整性。通过对比哈希值,可以判断数据是否被篡改或损坏。

(2)大家可以去 LeetCode 上找相关的字符串匹配的题目来练习,或者也可以直接查看 LeetCode 算法刷题目录 (Java) 这篇文章中的字符串章节。如果大家发现文章中的错误之处,可在评论区中指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1277377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于ASP.NET MVC技术的图书管理系统的设计与实现

基于ASP.NET MVC技术的图书管理系统的设计与实现 摘要&#xff1a;图书管理系统是一套高新科学技术和图书知识信息以及传统历史文化完美结合的体现。它改变了传统图书收藏的静态书本式图书服务特征&#xff0c;实现了多媒体存取、远程网络传输、智能化检索、跨库无缝链接、创造…

景联文科技数据标注平台助力AI数据实现价值最大化

随着人工智能技术不断进步&#xff0c;应用领域不断拓宽&#xff0c;对于高质量、大规模标注数据的需求也在不断增加。 数据标注是人工智能行业的基石。机器学习需要运用海量的有效数据来做支撑&#xff0c;而这些数据就需要我们的标注员对其进行分析和处理&#xff0c;想要得到…

Linux Makefile的认识及CMake的使用

1 Makefile的作用 Makefile 指的是一个叫 Makefile 的文件,里面提前写了一些指令。每次要自动化的完成一个比较复杂项目的自动编译用的时候,就在命令行输入“make”命令Makefile使用。使用Makefile可以 “智能” 的知道: 1 哪些文件需要先进行编译。 2 当某一文件在某次mak…

第九节HarmonyOS 常用基础组件5-LoadingProgress

一、LoadingProgress LoadingProgress组件用于显示加载动效的组件&#xff0c;比如应用的登录界面&#xff0c;当我们点击登录的时候&#xff0c;显示的“正在登录”的进度条状态。LoadingProgress的使用非常简单&#xff0c;只需要设置颜色和宽高就可以了。 Entry Component …

可可爱爱的羽绒服,面料是三防的哦

分享女儿的时尚穿搭 粉粉嫩嫩的羽绒服 杜邦三防面料 柔软蓬松上身很舒适 超足充绒量 美观与实用性兼具 这款还有妈妈款哦&#xff01;&#xff01;

Innodb-ruby深入探索Innodb存储结构

达在之前已经分享过Innodb数据存储结构知识&#xff0c;但是都是基于理论原理知识理解&#xff0c;今天利用Innodb文件解析工具ruby进行探索Innodb真实的存储结构。 索引原理过程&#xff1a;【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引_innodb的聚集索引的数据插入_Surviv…

常用sql记录

备份一张表 PostgreSQL CREATE TABLE new_table AS SELECT * FROM old_table;-- 下面这个比上面好&#xff0c;这个复制表结构时&#xff0c;会把默认值、约束、注释都复制 CREATE TABLE new_table (LIKE old_table INCLUDING ALL) WITHOUT OIDS; INSERT INTO new_table SELE…

【vSphere 8 自签名 VMCA 证书】企业 CA 签名证书替换 vSphere VMCA CA 证书Ⅲ—— 颁发自签名与替换 VMCA 证书

目录 5. 使用 Microsoft 证书颁发机构颁发自签名 CA 证书链5.1 登录MADCS5.2 申请证书5.3 选择证书类型5.4 提交CR5.5 下载 Base 64 编码的证书5.6 将证书链传入VC 6. 使用 企业CA签发的 VMCA 证书 替换 vSphere 默认 VMCA 证书6.1 确认证书文件6.2 替换默认 vSphere 证书6.3 验…

【golang】为什么使用goland终端修改不了Go语言的配置环境?

问题 最近在做项目时&#xff0c;需要使用golang的交叉编译&#xff0c;在windows系统上打包一个可以在linux系统上运行的golang程序的二进制文件。 这就需要暂时修改一下golang的配置环境&#xff1a; set GOARCH amd64 set GOOS linux但是修改的时候发现在goland终端输入…

企业加密软件有哪些(公司防泄密软件)

企业加密软件是专门为企业设计的软件&#xff0c;旨在保护企业的敏感数据和信息安全。这些软件通过使用加密技术来对数据进行加密&#xff0c;使得数据在传输和存储过程中不会被未经授权的人员获取和滥用。 企业加密软件的主要功能包括数据加密、文件加密、文件夹加密、移动设备…

字营销具有成本效益的 5 个原因

任何企业的主要支出之一是他们花在营销上的钱。营销是每个企业保持对目标受众可见度并转化潜在客户的基本必要条件。品牌保持营销联盟的一种行之有效的方法是数字营销。在这个数字时代&#xff0c;对于所有希望在市场上建立品牌的企业来说&#xff0c;数字营销都是一种具有成本…

Beta冲刺随笔-DAY4-橘色肥猫

这个作业属于哪个课程软件工程A这个作业要求在哪里团队作业–站立式会议Beta冲刺作业目标记录Beta冲刺Day4团队名称橘色肥猫团队置顶集合随笔链接Beta冲刺笔记-置顶-橘色肥猫-CSDN博客 文章目录 SCRUM部分站立式会议照片成员描述 PM报告项目程序&#xff0f;模块的最新运行图片…

【halcon】裁剪

前言 目前我遇到的裁剪相关的函数都是以clip打头的函数。一共4个&#xff1a; clip_end_points_contours_xldclip_contours_xldclip_regionclip_region_rel 前面两个是对轮廓的裁剪。 后面是对区域的裁剪。 裁剪轮廓的两端 clip_end_points_contours_xld 用于实现裁剪XLD…

6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动

Minifilter 是一种文件过滤驱动&#xff0c;该驱动简称为微过滤驱动&#xff0c;相对于传统的sfilter文件过滤驱动来说&#xff0c;微过滤驱动编写时更简单&#xff0c;其不需要考虑底层RIP如何派发且无需要考虑兼容性问题&#xff0c;微过滤驱动使用过滤管理器FilterManager提…

第九节HarmonyOS 常用基础组件3-TextInput

一、TextInput描述 TextInput组件用于输入单行文本&#xff0c;响应输入事件。TextInput的使用也非常广泛&#xff0c;例如应用登录账号密码、发送消息等。和Text组件一样&#xff0c;TextInput组件也支持文本样式设置&#xff0c;下面的示例代码实现了一个简单的输入框&#x…

css所有属性介绍

文章目录 1️⃣ CSS属性介绍1.1 CSS3 动画属性&#xff08;Animation&#xff09;1.2 CSS 背景属性&#xff08;Background&#xff09;1.3 CSS 边框属性&#xff08;Border 和 Outline&#xff09;1.4 Box 属性1.5 Color 属性1.6 Content for Paged Media 属性1.7 CSS 尺寸属性…

prometheus部署及与grafana结合应用

一、prometheus 介绍 prometheus server 是 Prometheus组件中的核心部分&#xff0c;负责实现对监控数据的获取&#xff0c;存储以及查询。它会定期从静态配置的监控目标或者基于服务发现自动配置的自标中进行拉取数据&#xff0c;当新拉取到的数据大于配置的内存缓存区时&…

虚拟机备份数据自动化验证原理

备份数据成功备份下来了&#xff0c;但是备份数据是否可用可靠&#xff1f;对于这个问题&#xff0c;最好最可靠的方法是将备份数据实际恢复出来验证。 但是这样的方法&#xff0c;不仅费时费力&#xff0c;而且需要随着备份数据的定期产生&#xff0c;还应当定期做备份数据验…

MacDroid Pro for Mac – 安卓设备文件传输助手,实现无缝连接与传输!

想要在Mac电脑上轻松管理和传输您的安卓设备文件吗&#xff1f;MacDroid Pro for Mac 是您的最佳选择&#xff01;这款强大的文件传输助手可以让您在Mac上与安卓设备之间实现快速、方便的文件传输。 MacDroid Pro for Mac 提供了简单易用的界面&#xff0c;让您能够直接在Mac上…

逻辑卷管理器lvm

啥意思&#xff0c;个人理解就是可以将物理分区合并一起组成大的磁盘&#xff0c;也可以移除其中的某个分区。 有四个概念需要了解下 PV&#xff0c;物理卷&#xff0c;VG 卷用户组&#xff0c;PE物理扩展块&#xff0c;LV逻辑卷 p物理&#xff0c;v卷&#xff0c;g用户组&a…