首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 为什么要学习数据结构和算法?
02 | 如何抓住重点,系统高效地学习数据结构与算法?
03 | 复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?
04 | 复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度
05 | 数组:为什么很多编程语言中数组都从0开始编号?
06 | 链表(上):如何实现LRU缓存淘汰算法?
07 | 链表(下):如何轻松写出正确的链表代码?
08 | 栈:如何实现浏览器的前进和后退功能?
09 | 队列:队列在线程池等有限资源池中的应用
10 | 递归:如何用三行代码找到“最终推荐人”?
11 | 排序(上):为什么插入排序比冒泡排序更受欢迎?
12 | 排序(下):如何用快排思想在O(n)内查找第K大元素?
13 | 线性排序:如何根据年龄给100万用户数据排序?
14 | 排序优化:如何实现一个通用的、高性能的排序函数?
15 | 二分查找(上):如何用最省内存的方式实现快速查找功能?
16 | 二分查找(下):如何快速定位IP对应的省份地址?
17 | 跳表:为什么Redis一定要用跳表来实现有序集合?
18 | 散列表(上):Word文档中的单词拼写检查功能是如何实现的?
19 | 散列表(中):如何打造一个工业级水平的散列表?
20 | 散列表(下):为什么散列表和链表经常会一起使用?
21 | 哈希算法(上):如何防止数据库中的用户信息被脱库?
22 | 哈希算法(下):哈希算法在分布式系统中有哪些应用?
23 | 二叉树基础(上):什么样的二叉树适合用数组来存储?
24 | 二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?
25 | 红黑树(上):为什么工程中都用红黑树这种二叉树?
26 | 红黑树(下):掌握这些技巧,你也可以实现一个红黑树
27 | 递归树:如何借助树来求解递归算法的时间复杂度?
28 | 堆和堆排序:为什么说堆排序没有快速排序快?
29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?
30 | 图的表示:如何存储微博、微信等社交网络中的好友关系?
31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系?
32 | 字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?
33 | 字符串匹配基础(中):如何实现文本编辑器中的查找功能?
34 | 字符串匹配基础(下):如何借助BM算法轻松理解KMP算法?
35 | Trie树:如何实现搜索引擎的搜索关键词提示功能?
36 | AC自动机:如何用多模式串匹配实现敏感词过滤功能?
37 | 贪心算法:如何用贪心算法实现Huffman压缩编码?
38 | 分治算法:谈一谈大规模计算框架MapReduce中的分治思想
39 | 回溯算法:从电影《蝴蝶效应》中学习回溯算法的核心思想
40 | 初识动态规划:如何巧妙解决“双十一”购物时的凑单问题?
41 | 动态规划理论:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题
42 | 动态规划实战:如何实现搜索引擎中的拼写纠错功能?
43 | 拓扑排序:如何确定代码源文件的编译依赖关系?
44 | 最短路径:地图软件是如何计算出最优出行路径的?
45 | 位图:如何实现网页爬虫中的URL去重功能?
46 | 概率统计:如何利用朴素贝叶斯算法过滤垃圾短信?
47 | 向量空间:如何实现一个简单的音乐推荐系统?
48 | B+树:MySQL数据库索引是如何实现的?
49 | 搜索:如何用A*搜索算法实现游戏中的寻路功能?
50 | 索引:如何在海量数据中快速查找某个数据?
51 | 并行算法:如何利用并行处理提高算法的执行效率?
52 | 算法实战(一):剖析Redis常用数据类型对应的数据结构
53 | 算法实战(二):剖析搜索引擎背后的经典数据结构和算法
54 | 算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法
55 | 算法实战(四):剖析微服务接口鉴权限流背后的数据结构和算法
56 | 算法实战(五):如何用学过的数据结构和算法实现一个短网址系统?
当前位置:
首页>>
技术小册>>
数据结构与算法之美
小册名称:数据结构与算法之美
### 34 | 字符串匹配基础(下):如何借助BM算法轻松理解KMP算法? 在数据结构与算法的世界里,字符串匹配是一个既基础又核心的问题,它广泛应用于文本搜索、生物信息学、网络安全等多个领域。在前几章,我们已经初步探讨了字符串匹配的基本概念及几种基础算法,如朴素匹配算法和Rabin-Karp算法。本章节,我们将深入字符串匹配的进阶领域,通过引入Boyer-Moore(BM)算法这一高效算法,来辅助理解更为复杂的KMP(Knuth-Morris-Pratt)算法。BM算法以其卓越的跳跃性能著称,而KMP算法则以其巧妙的“部分匹配表”闻名,两者虽方法不同,但在理解字符串匹配的高效性上有着异曲同工之妙。 #### 一、Boyer-Moore算法概览 Boyer-Moore算法是一种高效的字符串匹配算法,它主要通过两种启发式策略来减少不必要的比较次数:坏字符规则(Bad Character Rule)和好后缀规则(Good Suffix Rule)。这两种规则使得算法在遇到不匹配时,能够大幅度地跳过一些不可能包含匹配子串的文本区域,从而显著提高匹配效率。 - **坏字符规则**:当模式串P中的某个字符与主串T中相应位置的字符不匹配时,如果该字符在模式串P中其他位置也出现过,则可以安全地将模式串向右滑动,直到这个字符在模式串中的下一次出现位置对齐(或更右),因为在此之前的任何位置,该字符都不可能匹配。 - **好后缀规则**:当模式串P的后缀与主串T的某个位置匹配但整个模式串不匹配时,根据已经匹配的好后缀信息,可以推断出模式串应如何移动以寻找下一个可能的匹配位置。这一规则较为复杂,但能有效利用已匹配的信息减少搜索空间。 #### 二、KMP算法的核心思想 KMP算法同样是一种高效的字符串匹配算法,它解决了朴素匹配算法中每次仅移动一个字符的问题。KMP算法的核心在于,当遇到不匹配时,不是简单地将模式串向右移动一位,而是根据已经匹配的前缀信息,将模式串向右滑动尽可能多的位置,使得下一次比较能更有效地进行。 KMP算法的关键在于构建“部分匹配表”(也称为“失败函数”或“前缀函数”),该表记录了模式串中每个位置之前的子串中,最长相等前后缀的长度。当不匹配发生时,利用这个表,算法可以决定模式串应该向右滑动多少位。 #### 三、BM算法如何辅助理解KMP算法 虽然BM算法和KMP算法在实现细节和策略上大相径庭,但它们在处理字符串匹配时都展现出了对“已知信息”的高效利用和“无用比较”的有效避免。通过对比这两种算法,我们可以更深刻地理解字符串匹配中的“跳跃”思想,以及如何利用字符串的特性来优化搜索过程。 1. **跳跃策略的相似性**: - BM算法通过坏字符规则和好后缀规则实现跳跃,其中坏字符规则直接跳过了那些显然不可能包含匹配子串的文本区域。 - KMP算法则通过部分匹配表,在不匹配发生时,根据已匹配的前缀信息决定跳跃的距离,避免了重复比较已确认不匹配的部分。 两者都体现了在字符串匹配过程中,对“无用信息”的忽视和对“有用信息”的充分利用。 2. **对字符串特性的理解**: - BM算法通过识别坏字符和好后缀,实际上是在理解字符串中字符的分布和子串的重复性。 - KMP算法的部分匹配表则是对模式串自身特性的深入分析,它揭示了模式串内部结构的相似性,从而指导了搜索过程中的跳跃。 这两种算法都要求我们对字符串的特性有深入的理解,并据此设计出高效的匹配策略。 3. **优化思路的启发**: - BM算法和KMP算法都展示了在字符串匹配问题中,通过减少不必要的比较次数,可以显著提高算法的效率。这种优化思路不仅适用于字符串匹配,也可以推广到其他类似的搜索和匹配问题中。 - 它们还启示我们,在处理复杂问题时,应该尝试从问题本身出发,寻找其内在规律和特性,进而设计出更加高效、简洁的解决方案。 #### 四、KMP算法的具体实现 下面简要介绍KMP算法中部分匹配表的构建及匹配过程: 1. **构建部分匹配表**: - 遍历模式串P,对于每个位置i,计算以i结尾的子串中,最长相等前后缀的长度(不包括整个子串本身)。 - 将这些长度存储在部分匹配表中,以便在匹配过程中使用。 2. **匹配过程**: - 初始化两个指针,分别指向主串T和模式串P的起始位置。 - 逐字符比较T和P,直到遇到不匹配或P遍历完成。 - 当不匹配发生时,根据部分匹配表,将P向右滑动相应的距离,然后继续比较。 - 重复上述过程,直到找到匹配或确定T中不存在P。 #### 五、总结 通过对比BM算法和KMP算法,我们不仅加深了对字符串匹配问题的理解,还学会了如何利用字符串的特性来优化搜索过程。BM算法以其独特的跳跃策略和高效的匹配性能,为我们展示了一种全新的字符串匹配思路;而KMP算法则以其精巧的部分匹配表和高效的匹配过程,成为了字符串匹配领域的经典之作。两者虽方法不同,但都体现了在解决复杂问题时,对问题本身特性的深刻洞察和高效利用。希望本章的内容能够为您在数据结构与算法的学习之路上提供有益的启示和帮助。
上一篇:
33 | 字符串匹配基础(中):如何实现文本编辑器中的查找功能?
下一篇:
35 | Trie树:如何实现搜索引擎的搜索关键词提示功能?
该分类下的相关小册推荐:
编程之道-算法面试(下)
数据结构与算法(下)
算法面试通关 50 讲
数据结构与算法(上)
数据结构与算法(中)
业务开发实用算法精讲
编程之道-算法面试(上)