字符串匹配算法(一):BF算法和RK算法

字符串匹配算法(一):BF算法和RK算法
yngcy一、前言
字符串(String)是由一系列字符组成的数据类型,用于表示文本。字符可以是字母、数字、符号或其他特殊字符。在编程语言中,字符串通常用引号(单引号或双引号)括起来。
无论是在算法题中,还是在项目开发中,字符串都十分常见。我们经常在字符串中查找某个字符串,如 Java 的 indexOf()
方法。查找方法底层依赖字符串匹配算法,字符串匹配问题也是字符串问题的一个重要分支。
二、什么是字符串匹配
2.1 定义
字符串匹配问题的定义如下:
给定字符串
我们要在主串中查找模式串,要满足主串长度
大于模式串长度 ,否则就无法匹配。
2.2 分类
一般按照模式串的个数可以将字符串匹配问题分成两类:
- 单模式串匹配
- 多模式串匹配
单模式串匹配是指在主串中查找一个模式串的所有出现位置。而多模式串匹配是指在主串中同时查找多个模式串的所有出现位置。
常见的单模式串匹配算法有:
- BF(Brute Force)算法:暴力匹配算法
- RK(Rabin-Karp)算法:基于哈希的字符串匹配算法
- KMP算法:利用部分匹配表进行快速匹配
- BM算法:从模式串末尾开始匹配
- Sunday算法:在BM算法基础上的改进算法
常见的多模式串匹配算法有:
- AC自动机:基于Trie树实现的多模式串匹配算法
- WM(Wu-Manber)算法:基于BM算法的多模式串匹配算法
本文将重点介绍BF算法和RK算法,它们是字符串匹配算法中最基础的两种算法。后续文章会介绍其他更高效的字符串匹配算法。
三、BF算法
BF 算法是暴力算法(Brute Force)的简称。它比较好理解,但是匹配效率不高。
它的核心思路是,模式串的长度是固定的,因此可以遍历主串,枚举子串的起始位置,即
可以从上面的匹配过程中看出,每次匹配要匹配
四、RK算法
RK 算法全称是 Rabin-Karp 算法,它是基于哈希算法的暴力算法。前面的 BF 算法中,对比子串与模式串时依次比较每个字符,所以时间复杂度就比较高,为
RK 算法的核心思路时在比较前计算子串的哈希值是否与模式串相等,如果相等则比较字符是否相等,否则就继续遍历。相当于在比较前设了一个“门槛”,只有过了“门槛”才会比较,省去了一些无用的比较,从而提高效率。
如果你不了解什么是哈希算法,也没关系,下面我来简单讲讲哈希算法。
我们知道函数映射,如
现在我们来看看 RK 算法是如何设计哈希函数的。
假设字符集的大小为
比如字符集是从 a ~ z 这 26 个小写字母,于是用 0 ~ 25 分别表示它们。例如计算“abc”的哈希值的过程如下:
现在我们来分析 RK 算法的复杂度,扫描主串的时间复杂度是
所以为了能够比较,我们允许发生哈希冲突,也就是对哈希值取模,将哈希值限定在某个可表示的范围内。当发生哈希冲突时,再比较两个字符串是否相同。现在关键是如何减小发生冲突的概率。一种常见的优化方法是双值哈希:得出的哈希值对两个质数取模,可以降低发生冲突的概率。
虽然 RK 算法无法避免发生哈希冲突,最坏情况下会退化成
五、写在最后
今天介绍了两个字符串比较算法:BF 算法和 RK 算法。两个算法理解起来都比较简单。
BF 算法是朴素做法,截取每个子串依次与模式串进行比较。时间复杂度较高,但是因为理解起来简单,因此在开发中也用的最多。
RK 算法利用哈希算法对 BF 算法进行改进。它还是会遍历每个子串,但是在比较子串与模式串之前,会先计算它们的哈希值,如果哈希值不相等则不用比较,减少比较次数,效率更高。RK 算法比较依赖哈希算法的设计,哈希冲突越少,效率越高。RK 算法的时间复杂度为
如果你对本文有什么疑问或新的想法,欢迎评论!后续内容也会补充相关的练习题~🦭