当前位置: 首页 > news >正文

字符串匹配的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 多平台发布

相关文章:

字符串匹配的Rabin–Karp算法

leetcode-28 实现strStr() 更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法 一般中文译作 拉宾-卡普算法,由迈克尔拉宾与理查德卡普于1987年提出 “ 要在一段文本中找出单个模式串的一个匹配&#xff0c;此算法具有线性时间的平均复杂度&#xff0…...

傅里叶变换(FFT)笔记存档

参考博客&#xff1a;https://www.luogu.com.cn/blog/command-block/fft-xue-xi-bi-ji 目录&#xff1a; FFT引入复数相关知识单位根及其相关性质DFT过程&#xff08;难点&#xff09;DFT结论&#xff08;重要&#xff09;IDFT结论&#xff08;重要&#xff09;IDFT结论证明&…...

ELK安装、部署、调试 (二) ES的安装部署

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口操作ES&#xff0c;也可以利用Java API。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业…...

Android 13 - Media框架(8)- MediaExtractor

上一篇我们了解了 GenericSource 需要依赖 IMediaExtractor 完成 demux 工作&#xff0c;这一篇我们就来学习 android media 框架中的第二个服务 media.extractor&#xff0c;看看 IMediaExtractor 是如何创建与工作的。 1、MediaExtractorService media.extractor 和 media.p…...

Flutter 混合开发调试

针对Flutter开发的同学来说&#xff0c;大部分的应用还是Native Flutter的混合开发&#xff0c;所以每次改完Flutter代码&#xff0c;运行整个项目无疑是很费时间的。所以Flutter官方也给我们提供了混合调试的方案【在混合开发模式下进行调试】&#xff0c;这里以Android Stud…...

C语言每日一练------(Day3)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今天练习题的关键字&#xff1a; 尼科彻斯定理 等差数列 &#x1f493;博主csdn个人主页&#xff1a…...

14、监测数据采集物联网应用开发步骤(10)

监测数据采集物联网应用开发步骤(9.2) Modbus rtu协议开发 本章节在《监测数据采集物联网应用开发步骤(7)》基础上实现可参考《...开发步骤(7)》调试工具&#xff0c;本章节代码需要调用modbus_tk组件&#xff0c;阅读本章节前建议baidu熟悉modbus rtu协议内容 组件安装modb…...

Linux禅道上修改Apache 和 MySQL 默认端口号

1. 修改Apache默认端口号 80 cd /opt/zbox/etc/apachevim httpd.conf :wq 保存 2. 修改MySQL默认端口号 3306 cd /opt/zbox/etc/mysql vim my.cnf :wq 保存 3. 重启服务 ./zbox restart...

操作教程|通过1Panel开源Linux面板快速安装DataEase

DataEase开源数据可视化分析工具&#xff08;dataease.io&#xff09;的在线安装是通过在服务器命令行执行Linux命令来进行的。但是在实际的安装部署过程中&#xff0c;很多数据分析师或者业务人员经常会因为不熟悉Linux操作系统及命令行操作方式&#xff0c;在安装DataEase的过…...

机器学习策略——优化深度学习系统

正交化&#xff08;Orthogonalization&#xff09; 老式电视机&#xff0c;有很多旋钮可以用来调整图像的各种性质&#xff0c;对于这些旧式电视&#xff0c;可能有一个旋钮用来调图像垂直方向的高度&#xff0c;另外有一个旋钮用来调图像宽度&#xff0c;也许还有一个旋钮用来…...

ES6中Proxy和Proxy实例

1.Proxy Proxy 这个词的原意是代理&#xff0c;用在这里表示由它来“代理”某些操作&#xff0c;可以译为“代理器” 使用方法 let p new Proxy(target, handler);其中&#xff0c;target 为被代理对象。handler 是一个对象&#xff0c;其声明了代理 target 的一些操作。p 是…...

UDP协议的重要知识点

UDP&#xff0c;即用户数据报协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;是一个简单的无连接的传输层协议。与TCP相比&#xff0c;UDP提供了更少的错误检查机制&#xff0c;并允许数据包在网络上更快地传输。在这篇博客中&#xff0c;我们将深入探讨UDP的…...

QT6为工程添加资源文件,并在ui界面引用

以添加图片资源为例 右键工程名字&#xff08;不是最上面的名字&#xff09;&#xff0c;点击添加现有文件 这种方式虽然添加到了工程中&#xff0c;但不能在UI设计界面完成引用。主要原因可能是未把文件放入到项目资源文件中&#xff0c;以下面一种方式可以看出区别。 点击添…...

Python小知识 - 如何使用Python的Flask框架快速开发Web应用

如何使用Python的Flask框架快速开发Web应用 现在越来越多的人把Python作为自己的第一语言来学习&#xff0c;Python的简洁易学的语法以及丰富的第三方库让人们越来越喜欢上了这门语言。本文将介绍如何使用Python的Flask框架快速开发Web应用。 Flask是一个使用Python编写的轻量级…...

Flutter 项目结构文件

1、Flutter项目的文件结构 先helloworld项目&#xff0c;看看它都包含哪些组成部分。首先&#xff0c;来看一下项目的文件结构&#xff0c;如下图所示。 2、介绍上图的内容。 -litb/main.dart文件&#xff1a;整个应用的入口文件&#xff0c;其中的main函数是整个Flutter应…...

未找到System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid) 方法错误

记录此问题实际上是由于.netFrame框架配置太高引起的&#xff0c;一般常见于二次开发中&#xff0c;因为二次开发一般都是引用的com组件&#xff0c;在引用过程中后台代码调用了 Method not found: System.Type System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(Syste…...

人员位置管理,点亮矿山安全之路

矿山作为一个高危行业&#xff0c;安全问题一直备受关注。人员定位置管理是现代矿山安全管理的重要一环&#xff0c;可以帮助企业更好地实现对人员的实时监控和管理。因此&#xff0c;矿山人员位置管理系统对于矿山安全生产和管理非常重要&#xff0c;可以帮助减少安全事故的发…...

node-red - 读写操作redis

node-red - 读写操作redis 一、前期准备二、node-red安装redis节点三、node-red操作使用redis节点3.1 redis-out节点 - 存储数据到redis3.2 redis-cmd节点 - 存储redis数据3.3 redis-in节点 - 查询redis数据 附录附录1&#xff1a;redis -out节点示例代码附录2&#xff1a;redi…...

【图像处理】模板匹配的学习笔记

OpenCV的模板匹配算法 cv.TM_CCOEFFcv.TM_CCOEFF_NORMEDcv.TM_CCORRcv.TM_CCORR_NORMEDcv.TM_SQDIFFcv.TM_SQDIFF_NORMED 匹配代码模板 image cv2.imread(r"scene.png", cv2.IMREAD_GRAYSCALE) template cv2.imread(r"element.png", cv2.IMREAD_GRAYSC…...

Ext JS之Ext Direct快速入门

Ext Direct是一个专有名词, Direct是直接的意思。 Ext Direct 是 Ext JS 框架中的一个功能模块,用于简化前端 JavaScript 应用程序与后端服务器之间的通信和数据交换。 Ext Direct 提供了一种直接的、透明的方式来调用服务器上的方法和处理服务器响应,而无需编写大量的手动…...

内网隧道技术学习

1. 隧道技术 在进行渗透测试以及攻防演练的时候&#xff0c;通常会存在各种边界设备、软硬件防火墙、IPS等设备来检测外部连接情况&#xff0c;这些设备如果发现异常&#xff0c;就会对通信进行阻断。 那么隧道技术就是一种绕过端口屏蔽的通信方式&#xff0c;在实际情况中防…...

【前端】CSS3新特性

目录 一、前言二、伪元素选择器1、选择器2、注意事项3、代码示例 三、伪元素清除浮动1、第一种伪元素清除浮动2、第二种伪元素清除浮动 四、CSS3盒子模型1、box-sizing&#xff1a;content-box2、box-sizing&#xff1a;border-box 五、CSS3图片模糊处理1、图片变模糊①、CSS3滤…...

Spring之HandlerInterceptor和RequestBodyAdvice

一个请求在Spring中处理流程是有多种方式拦截处理的&#xff0c;而且&#xff0c;请求是可以拆分为进入和响应2个操作的&#xff0c;进入我们通常会对请求参数做处理&#xff0c;而响应我们通常会对响应参数做处理&#xff0c;Spring提供了多种方式给开发者。 一、HandlerInte…...

transition、transform 区别和应用

先说应用 1.动画循环&#xff0c;复杂的动画用animation。在遇到很复杂的动画那就用animation。因为animation可以定义关键帧。那你就可以控制每一帧的动画效果。 2.简单的动画&#xff0c;事件触发用transition。当页面中的动画是自己执行的那么我们考虑用animation&#xf…...

Android中级——消息机制

消息机制 概念ThreadLocalMessageQueueLooperHandlerrunOnUiThread() 概念 MessageQueue&#xff1a;采用单链表的方法存储消息列表Looper&#xff1a;查询MessageQueue是否有新消息&#xff0c;有则处理&#xff0c;无则等待ThreadLocal&#xff1a;用于Handler获取当前线程的…...

【kubernetes】使用KubeSphere devops部署我的微服务系统

KubeSphere Devops 入门使用KubeSphere的Devops功能部署"我的微服务系统" &#xff08;内容学习于尚硅谷云原生课程&#xff09; kubesphere devops官方文档&#xff1a; https://v3-1.docs.kubesphere.io/zh/docs/devops-user-guide/how-to-use/create-a-pipeline-u…...

【哈士奇赠书活动 - 37期】- 〖深入浅出SSD:固态存储核心技术、原理与实战 第2版〗

文章目录 ⭐️ 赠书 - 《深入浅出SSD&#xff1a;固态存储核心技术、原理与实战 第2版》⭐️ 内容简介⭐️ 作者简介⭐️ 编辑推荐⭐️ 赠书活动 → 获奖名单 ⭐️ 赠书 - 《深入浅出SSD&#xff1a;固态存储核心技术、原理与实战 第2版》 ⭐️ 内容简介 本书从基础认知、核心技…...

25.CSS自定义形状按钮与悬停效果

效果 源码 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>CSS Custom Shape Button</title><link rel="stylesheet" href="style.css"> </head> <body&…...

两条速度相差1350倍的sql语句

一起来学习研究下&#xff0c;看看是什么导致的这么大差别&#xff1a; SQL1: select * from RESOURCES where RES_STATUS 1 and PLATFORM_FLAG1 and RES_ID in (select RES_ID from DOWNLOADRECORDSwhere DOWNLOADRECORDS_TIME > DATE_SUB(now(),INTERVAL 7 DAY) grou…...

【UniApp开发小程序】小程序首页完善(滑到底部数据翻页、回到顶端、基于回溯算法的两列数据高宽比平衡)【后端基于若依管理系统开发】

文章目录 说明细节一&#xff1a;首页滑动到底部&#xff0c;需要查询下一页的商品界面预览页面实现 细节二&#xff1a;当页面滑动到下方&#xff0c;出现一个回到顶端的悬浮按钮细节三&#xff1a;商品分列说明优化前后效果对比使用回溯算法实现ControllerService回溯算法 优…...