数据结构与算法之美
王争
前 Google 工程师
283752 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 81 讲
基础篇 (38讲)
数据结构与算法之美
15
15
1.0x
00:00/00:00
登录|注册

32 | 字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?

哈希冲突处理:允许哈希冲突,再对比子串和模式串本身
子串哈希值计算:K进制数转化为十进制数
如何在二维字符串矩阵中查找另一个二维字符串矩阵
适用场景:处理大规模字符串匹配,效率较高
时间复杂度:O(n)
哈希算法设计:
思想:借助哈希算法对BF算法进行改造
适用场景:处理小规模的字符串匹配
时间复杂度:O(n*m)
思想:暴力匹配算法,逐个比对子串与模式串
二维字符串匹配
RK算法
BF算法
字符串匹配算法

该思维导图由 AI 生成,仅供参考

从今天开始,我们来学习字符串匹配算法。字符串匹配这样一个功能,我想对于任何一个开发工程师来说,应该都不会陌生。我们用的最多的就是编程语言提供的字符串查找函数,比如 Java 中的 indexOf(),Python 中的 find() 函数等,它们底层就是依赖接下来要讲的字符串匹配算法。
字符串匹配算法很多,我会分四节来讲解。今天我会讲两种比较简单的、好理解的,它们分别是:BF 算法和 RK 算法。下一节,我会讲两种比较难理解、但更加高效的,它们是:BM 算法和 KMP 算法。
这两节讲的都是单模式串匹配的算法,也就是一个串跟一个串进行匹配。第三节、第四节,我会讲两种多模式串匹配算法,也就是在一个串中同时查找多个串,它们分别是 Trie 树和 AC 自动机。
今天讲的两个算法中,RK 算法是 BF 算法的改进,它巧妙借助了我们前面讲过的哈希算法,让匹配的效率有了很大的提升。那RK 算法是如何借助哈希算法来实现高效字符串匹配的呢?你可以带着这个问题,来学习今天的内容。

BF 算法

BF 算法中的 BF 是 Brute Force 的缩写,中文叫作暴力匹配算法,也叫朴素匹配算法。从名字可以看出,这种算法的字符串匹配方式很“暴力”,当然也就会比较简单、好懂,但相应的性能也不高。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

字符串匹配算法的基础知识包括朴素匹配算法(BF算法)和RK算法。BF算法通过暴力匹配方式,在主串中逐个检查子串与模式串是否匹配,时间复杂度为O(n*m)。尽管时间复杂度较高,但在实际开发中仍常用,因为大部分情况下模式串和主串长度不会太长,且算法思想简单易实现。RK算法则是BF算法的改进,利用哈希算法提升匹配效率。通过哈希算法计算子串的哈希值,RK算法的时间复杂度可降至O(n)。然而,哈希冲突可能导致时间复杂度退化为O(n*m)。文章还提到了后续将介绍的BM算法、KMP算法、Trie树和AC自动机,展示了字符串匹配算法的多样性和实用性。读者可以快速了解字符串匹配算法的基本概念和应用场景,以及RK算法如何借助哈希算法实现高效字符串匹配。RK算法的特点在于借助哈希算法提高匹配效率,但需要注意哈希冲突可能导致效率下降。文章还提到了一维字符串匹配方法,为读者提供了思考和拓展的空间。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《数据结构与算法之美》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(196)

  • 最新
  • 精选
  • ZX
    RK算法,在对主串构建的时候,就对比是不是一样的,一样就不继续计算后面的hash,这样会不会更快一点

    作者回复: 你说的很对 代码实现就是这样处理的

    2018-12-06
    17
    208
  • ✨拓星✨
    基于BF的匹配算法平时的用的比较多,看完之后想了一会觉得没有什么情况会用到第二种RK算法的情况,因为平时业务关系可能没有做到相关的项目,所以想问老师一般什么场景会使用RK这种匹配算法呢?

    作者回复: 应该是比较刁钻的场景 我也没遇到过 平时都是直接用编程语言提供的函数。不过不耽误我们学习他的思想 技巧

    2018-12-06
    2
    25
  • Spider Man
    老师您应该把公式的推理过程简单地说一下,这公式对您来说非常简单,但是对于我这种基础差的人,完全是懵逼的状态。看着大家讨论,却无法深入下去。/(ㄒoㄒ)/~~

    作者回复: 我补一下

    2019-01-09
    20
  • coulson
    老师,前天面试被问到一个问题,关于地图算法的,比如线路推荐。请问地图算法会讲到么

    作者回复: 在高级篇那部分会涉及一点

    2018-12-05
    2
    17
  • Alan
    h[i] = 26*(h[i-1]-26^(m-1)*h[i-1]) + h[i+m-1]; 其中, h[i]、h[i-1] 分别对应 s[i] 和 s[i-1] 两个子串的哈希值 ------------------ 文中这个公式,26*(h[i-1]-26^(m-1)*h[i-1])可以化简为26*h[i-1]*(1-26^(m-1)),所以这里是不是应该改为26*(h[i-1]-26^(m-1)*s[i-1]),用s[i-1]代表当前位置的字符串的值,例如图中d的值是3,同样的公式后面加 h[i+m-1]是不是也是s[i+m-1]呢

    作者回复: 写错了 感谢指正 已经改了

    2018-12-05
    2
    16
  • 星君
    好几期没看了,感觉跟不上了

    作者回复: 不着急 慢慢来 没必要一直紧跟着

    2018-12-12
    2
    11
  • 漫漫越
    停看了好多天,最后还是决定继续跟随老师的脚步,为自己加油~

    作者回复: 停一停 歇歇挺好的 也没必要跟的很紧 搞的自己很窘迫

    2018-12-18
    7
  • Spider Man
    h[i] = 26*(h[i-1]-26^(m-1)*(s[i-1]-'a')) + (s[i+m-1]-'a'); 其中, h[i]、h[i-1] 分别对应 s[i] 和 s[i-1] 两个子串的哈希值 好吧,这一段代码我对照上下文看了10遍,看懂了。我承认我很蠢

    作者回复: 抱歉 没写清楚

    2019-01-09
    5
  • 菜鸡程序员
    可不可以先不遍历所有的hash值,而是移动一位算一位hash值,然后再对比,这样能否提高效率

    作者回复: 可以的

    2019-04-10
    2
    1
  • 菜鸡程序员
    为何不再生成子串的hash值时,把hash值存到一个hashmap中,这样就不用遍历数组了,可以根据目标的hash值,直接在map的链表中查找

    作者回复: 浪费空间呢

    2019-04-10
    1
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部