字符串匹配基础(上)

扫码关注公众号,获取更多内容

目录

一、BF算法

二、RK算法


一、BF算法

BF算法中文称作“暴力匹配算法”,也叫“朴素匹配算法”。

我们先来了解两个概念主串模式串。来看下面的例子:

比如说,在字符串A(长度为n)中查找字符串B(长度为m),那么字符串A就是主串,字符串B就是模式串。因为我们是在主串中查找模式串,所以n>m。

BF算法可以用一句话来概括:我们在主串中,检查起始位置分别是 0、1、2....n-m 且长度为 m 的 n-m+1 个子串,看有没有跟模式串匹配的。如下图所示:

从上面的例子和算法思想我们可以知道,在极端情况下,比如主串是“aaaaaa....aaaaaa”(.....代表有多个a),模式串是aaaaab。我们每次都比对m个字符串,要对比n-m+1次,所以,这种算法的最坏情况时间复杂度是O(n*m)。

尽管BF算法的时间复杂度很高,但在实际开发中,它却是一个比较常用的字符串匹配算法,原因有两点:

1、实际中,主串和模式串的长度都不会太长。

2、朴素字符串匹配算法思想简单,代码也非常简单。不容易出错,如果有bug也比较容易修复。

 

二、RK算法

在之前所讲述的BF算法中,如果模式串长度为m,主串长度为n,那在主串中,就会有n-m+1个长度为m的子串,我们只需要暴力对比这n-m+1个子串与模式串,就可以找出主串与模式串匹配的子串。

但是每次检查主串与子串是否匹配的时候,都需要依次对比每个字符,所以BF算法的时间复杂度就比较高(O(n*m))。我们引入哈希算法对其进行改造,时间复杂度就会降低。

思路:通过哈希算法对主串中的n-m+1个子串分别求哈希值,然后逐个与模式串的哈希值比较大小,如果某个子串的哈希值与模式串相等,那就说明对应的子串和模式串匹配了,因为哈希值是一个数字,数字之间比较是否相等非常快速,所以模式串和子串比较的效率就提高了。

不过,通过哈希算法计算子串的哈希值的时候,我们需要遍历子串中的每个字符。尽管模式串与子串比较的效率提高了,但是算法的整体效率并没有提高,这个问题怎么解决呢?

这就需要哈希算法的设计的非常有技巧了。假设我们要匹配的字符串的字符集中只包含K个字符,我们可以用一个K进制数来表示一个子串,这个K进制数转化为十进制数,作为子串的哈希值。

比如要处理的字符串只包含a-z这26个字母,那我们就用二十六进制来表示一个字符串。我们把a~z这26个字符串映射到0-25这26个数字,a就表示0,b就表示1,c表示2,以此类推,z表示25。

在十进制的表示法中,一个数字的值是通过下面的方式计算出来的,对应到二十六进制,一个包含a-z的这26个字符串的字符串,计算哈希的时候,我们只需要把进位从10改成26就可以了。

为了方便解释,在下面,我们假设字符串只包含a-z这26个小写字符,我们用二十六进制来表示一个字符串,对应的哈希值就是二十六进制转化为十进制的结果。

这种算法有一个特点,在主串中,相邻两个子串的哈希值的计算公式有一定关系,来看下面的例子:

从上面的例子中,我们能得到一个规律:相邻两个子串 s[i-1] 和 s[i] (i表示子串在主串中的起始位置,子串的长度都为m),对应的哈希公式有交集,这就说明,我们可以使用s[i-1]的哈希值很快的计算出s[i]的哈希值。用公式表示的话,是下面的样子:

有个小细节需要注意,26^(m-1) 这部分的计算,我们可以通过查表的方法来提高效率。事先计算好26^0、26^1、26^2……26^(m-1),并且存储在一个长度为m的数组中,公式中的“次方”对应数组的下标。当需要计算26的x次方的时候,就可以从数组的下标为x的位置取值,直接使用,省去了计算的时间。

整个RK算法包含两部分:

1、计算子串哈希值。

2、模式串哈希值与子串哈希值之间比较。

其中第一部分,可以通过前面介绍的设计特殊的哈希算法,主需要扫描一遍主串就能计算出所有子串的哈希值了,所以这部分时间复杂度是O(n)。

模式串哈希值与每个子串哈希值之间的比较的时间复杂度是O(1),总共需要比较n-m+1个子串的哈希值,所以,这部分的时间复杂度也是O(n),所以,RK算法的整体的时间复杂度就是O(n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值