字符串匹配的Rabin–Karp算法


leetcode-28 实现strStr()

更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法



一般中文译作 拉宾-卡普算法,由迈克尔·拉宾与理查德·卡普于1987年提出

要在一段文本中找出单个模式串的一个匹配,此算法具有线性时间的平均复杂度,其运行时间与待匹配文本和模式串的长度成线性关系。虽然平均情况下,此算法表现优异,但最坏情况下,其复杂度为文本长与模式串长的乘积

尽可能多的利用上一步的结果,这是优化时间复杂度的一大核心


对于数字类型的字符串,可有如下匹配方法:


alt

将该方法扩展到非数字类型的字符串:


alt
以上这张图片的LaTex:
$$\begin{gather}
  
对于长度为n的字符串 x_{0} x_{1} x_{2} ... x_{n-1},\\其对应的“值”val为\\

val = x_{0} \times r^{n-1} + x_{1}\times r^{n-2} + ... +  x_{n-1}\times r^{0}
 
 \\其中r为进制数\end{gather}$
alt
alt

ASCII:英语字符与二进制位之间的关系 (其他语言??)

Unicode:将世界上所有的符号都纳入其中, 每个符号都对应一个独一无二的编码,最多可以容纳1114112个字符(2021年9月公布的14.0.0,已经收录超过14万个字符) (有个问题是浪费空间。。) 也译作统一码/万国码/国际码

UTF-8: 使用最广的一种 Unicode 的实现方式 (最大特点是 变长的编码方式)

字符编码笔记:ASCII,Unicode 和 UTF-8

中日韩汉字Unicode编码表


源码注释:


alt

将源码中的16777619进制改为10进制,从字符串31415926中搜索4159:

4159

package main

import (
 "fmt"
 "strconv"
)

func main() {

 var primeRK uint32 = 10
 sep := "4159"
 hash := uint32(0)
 for i := 0; i < len(sep); i++ {

  //fmt.Println(sep[i])
  //fmt.Println(string(sep[i]))
  next, _ := strconv.Atoi(string(sep[i]))
  //hash = hash*primeRK + uint32(sep[i])
  hash = hash*primeRK + uint32(next)
  fmt.Println(hash)
 }
 
}

输出为:

4
41
415
4159

完整的以10为primeRK,从31415926中搜索4159的代码:

package main

import (
 "fmt"
 "strconv"
)

const PrimeRKNew = 10

func main() {
 str := `31415926`
 substr := "4159"

 fmt.Println("最终结果为:",  IndexRabinKarpNew(str, substr))
}

func HashStrNew(sep string) (uint32uint32) {
 hash := uint32(0)

 for i := 0; i < len(sep); i++ {
  //fmt.Println(sep[i])
  //fmt.Println(string(sep[i]))
  next, _ := strconv.Atoi(string(sep[i]))
  //hash = hash*primeRK + uint32(sep[i])
  hash = hash*PrimeRKNew + uint32(next)
  fmt.Println(hash)
 }

 var pow, sq uint32 = 1, PrimeRKNew
 for i := len(sep); i > 0; i >>= 1 {
  fmt.Println("i is:", i, "---""i&1 is:", i&1)
  if i&1 != 0 {
   pow *= sq
  }
  sq *= sq
  fmt.Println("pow is:", pow)
 }
 return hash, pow
}

func IndexRabinKarpNew(s, substr string) int {
 // Rabin-Karp search
 hashss, pow := HashStrNew(substr)
 fmt.Println("hashss, pow:", hashss, pow)

 fmt.Println("~~~分割线~~~")

 n := len(substr)
 var h uint32
 for i := 0; i < n; i++ {
  next1, _ := strconv.Atoi(string(s[i]))
  //h = h*PrimeRKNew + uint32(s[i])
  fmt.Println("next1 is:", next1)
  h = h*PrimeRKNew + uint32(next1)
 }

 fmt.Println("h即T串初始值为:", h)

 if h == hashss && s[:n] == substr {
  return 0
 }
 for i := n; i < len(s); {
  h *= PrimeRKNew
  fmt.Println("h*=:", h)

  last, _ := strconv.Atoi(string(s[i])) //当前T串的最后一个元素
  fmt.Println("last is:", last)
  //h += uint32(s[i])
  h += uint32(last)
  fmt.Println("h+=:", h)

  //h -= pow * uint32(s[i-n])
  first, _ := strconv.Atoi(string(s[i-n])) //当前T串的第一个元素
  fmt.Println("first is:", first)
  h -= pow * uint32(first)
  fmt.Println("h-=:", h)

  i++
  fmt.Println("---下次循环的 i为 ---", i)
  if h == hashss && s[i-n:i] == substr { //s[i-n:i]为当前的T串
   return i - n
  }
 }
 return -1
}

输出为:

4
41
415
4159
i is: 4 --- i&1 is: 0
pow is: 1
i is: 2 --- i&1 is: 0
pow is: 1
i is: 1 --- i&1 is: 1
pow is: 10000
hashss, pow: 4159 10000
~~~分割线~~~
next1 is: 3
next1 is: 1
next1 is: 4
next1 is: 1
h即T串初始值为: 3141
h*=: 31410
last is: 5
h+=: 31415
first is: 3
h-=: 1415
---下次循环的 i为 --- 5
h*=: 14150
last is: 9
h+=: 14159
first is: 1
h-=: 4159
---下次循环的 i为 --- 6
最终结果为: 2

strings.Contains()源码阅读暨internal/bytealg初探




书籍推荐

柔性字符串匹配


牛刀小试:

力扣28. 实现strStr()

力扣187. 重复的DNA序列

力扣686. 重复叠加字符串匹配



另:

除去KMP和RK算法,字符串匹配还有 Boyer-Moore算法(简称BM算法)系列算法,其核心思想是:

在字符串匹配过程中,模式串发现不匹配时,跳过尽可能多的字符以进行下一步的匹配,从而提高匹配效率

BM算法的简化版Horspool算法

以及性能更好的Sunday算法

Python用的也不是KMP,而是boyer-moore和horspool, 源码点此

KMP 算法的实际应用有哪些?

图解字符串匹配之Horspool算法和Boyer-Moore算法


本文由 mdnice 多平台发布

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

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

相关文章

Elasticsearch 高级搜索技巧和最佳实践

Elasticsearch 高级搜索技巧和最佳实践 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;它支持实时地存储、搜索和分析大规模数据。它被广泛应用于各行各业&#xff0c;用于构建高性能的搜索引擎、日志分析系统、电子商务推荐系统等。 本文将介…

【LeetCode-中等题】230. 二叉搜索树中第K小的元素

文章目录 题目方法一&#xff1a;层序遍历 集合排序方法二&#xff1a;中序遍历&#xff08;栈 或者 递归 &#xff09;方法三&#xff08;方法二改进&#xff09;&#xff1a;中序遍历&#xff08;栈 &#xff09; 题目 该题最大的特点就是这个树是二叉树&#xff1a; 所以…

【java中的Set集合】HashSet、LinkedHashSet、TreeSet(最通俗易懂版!!)

目录 一、HashSet集合 1.HashSet集合的特点 2.HashSet常用方法 二、LinkedHashSet集合 LinkedHashSet集合的特点 三、TreeSet集合 1.TreeSet集合的特点 2.TreeSet的基本使用 四、HashSet、LinkedHashSet、TreeSet的使用场景 五、list和set集合的区别 一、HashSet集合 …

go中的函数

demo1:函数的几种定义方式 package mainimport ("errors""fmt" )/* 函数的用法 跟其他语言的区别&#xff1a;支持多个返回值*///函数定义方法1 func add(a, b int) int {return a b }//函数定义方法2 func add2(a, b int) (sun int) {sun a breturn s…

数据库面试题分享(一)

文章目录 请简述数据库三大范式 ? 简述什么是SQL Server ? MySQL 如何优化SQL查询语句?重点 简述优化MySQL数据库的方法?重点 MySQL数据库,一天五万条以上的增量,预计运维三年怎么优化? 解释为什么Oracle type4驱动被称作瘦驱动? 如何理解数据库表设计的时候字段…

网页接口导入postman进行接口请求

postman版本&#xff1a;v10.17.4 一、拷贝接口信息 网页打开开发者工具-networkk&#xff0c;在网页上请求一次接口&#xff0c;鼠标指在接口上&#xff0c;点击鼠标右键-copy-copy as cURL(bash) 二、导入postman 打开postman&#xff0c;点击import-Raw text&#xff0c;…

YOLOv5、YOLOv7 注意力机制改进SEAM、MultiSEAM、TripletAttention

用于学习记录 文章目录 前言一、SEAM、MultiSEAM1.1 models/common.py1.2 models/yolo.py1.3 models/SEAM.yaml1.4 models/MultiSEAM.yaml1.5 SEAM 训练结果图1.6 MultiSEAM 训练结果图二、TripletAttention2.1 models/common.py2.2 models/yolo.py2.3 yolov7/cfg/training/Tri…

Spring Boot Actuator的Env端点存在本地文件包含(LFI)漏洞CVE-2020-5421

文章目录 0.前言1.参考文档2.基础介绍3.漏洞利用原理3.解决方案1. 升级Spring Boot版本2. 限制端点的访问3. 禁用环境端点4. 不公开敏感的Actuator端点5. 开启安全审计 0.前言 背景&#xff1a; Spring Boot Actuator的Env端点存在本地文件包含(LFI)漏洞CVE-2020-5421。被扫描到…

三维数据的显示及 L0D 模型

三维显示通常采用截面图、等距平面、多层平面和立体块状图等多种表现形 式&#xff0c;大多数三维显示技术局限于 CRT 屏幕和绘图纸的二维表现形式&#xff0c;人们可以观 察到地理现象的三维形状&#xff0c;但不能将它们作为离散的实体进行分析&#xff0c;如立体不能被 测…

【C51基础实验 LED闪烁】

51单片机项目基础篇 LED闪烁1、硬件电路设计和原理分析2、软件设计2.1、功能实现&#xff1a;LED闪烁2.2、通过 KEIL 软件自带仿真查看延时时间 4、编译结果5、结束语 LED闪烁 前言&#xff1a; 前一篇学会了点亮一颗LED以及驱动原理&#xff0c;那么这篇紧接着就来解锁LED的新…

【业务功能篇90】微服务-springcloud-检索服务-ElasticSearch实战运用-DSL语句

商城检索服务 1.检索页面的搭建 商品检索页面我们放在search服务中处理&#xff0c;首页我们需要在mall-search服务中支持Thymeleaf。添加对应的依赖 <!-- 添加Thymeleaf的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifa…

Nginx 通过userAgent判断是否时搜索引擎蜘蛛

Nginx配置如下 #爬虫转发if ($http_user_agent ~* "(Baiduspider|baiduspider|Baiduspider-render|bcebos-spider-1.0|baiduboxapp|360Spider|Sogou|Sogou web spider|Yisouspider|Googlebot|yahoo|ToutiaoSpider|bytespider|bingbot|YandexBot)") {rewrite ^/(.)/(.…

服务器安装 anaconda 及 conda: command not found [解决方案]

[解决方案] conda: command not found Anaconda3 安装conda: command not found Anaconda3 安装 由于连接的服务器&#xff0c;无法直接在anaconda官网上下载安装文件&#xff0c;所以使用如下方法&#xff1a; wget https://repo.anaconda.com/archive/Anaconda3-2023.03-Li…

(笔记二)利用opencv调用鼠标事件在图像上绘制图形

目录 &#xff08;1&#xff09;查看cv2所支持的鼠标事件&#xff08;2&#xff09;通过鼠标事件在图像上做标记&#xff08;3&#xff09;高级操作&#xff1a;通过移动鼠标在图像绘制图形、曲线 该功能主要创建一个鼠标事件发生时执行的回调函数。鼠标事件可以是任何与鼠标有…

根据身高重建队列【贪心算法】

根据身高重建队列 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返…

SQL注入漏洞复现(CVE-2017-8917)

文章目录 搭建环境启动环境漏洞复现报错注入使用sqlmap 前提条件&#xff1a; 1.安装docker docker pull medicean/vulapps:j_joomla_22.安装docker-compose docker run -d -p 8000:80 medicean/vulapps:j_joomla_23.下载vulhub Docker Compose是 docker 提供的一个命令行工具&…

Mysql中九种索引失效场景分析

表数据&#xff1a; 索引情况&#xff1a; 其中a是主键&#xff0c;对应主键索引&#xff0c;bcd三个字段组成联合索引&#xff0c;e字段为一个索引 情况一&#xff1a;不符合最左匹配原则 去掉b1的条件后就不符合最左匹配原则了&#xff0c;导致索引失效 情况二&#xff…

go学习-指针 标识符

指针&#xff0c;以及标识符 1.指针 &#xff08;1&#xff09;.基本介绍 1&#xff09;基本数据类型&#xff0c;变量存的值&#xff0c;也叫值类型 2&#xff09;获取变量的地址用&&#xff0c;比如 var num int ,获取num的地址&#xff1a;&num 3)指针类型&…

小程序隐私保护授权处理方式之弹窗组件

欢迎点击关注-前端面试进阶指南&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 小程序隐私保护授权弹窗组件 调用wx.getUserProfile进行授权时&#xff0c;返回错误信息&#xff1a;{errMsg: “getUserProfile:fail api scope is…

c++ 学习之 类的权限访问修改学习

先看代码 #define _CRT_SECURE_NO_WARNINGS #include <iostream>class person { public:// 在这里实现修改// 设置名字void set_name(string name){this->name name;}// 读取名字string get_name(){return name;}// 设置年龄并且打印年龄void fun(int age){age age…