单模式匹配算法,也就是一个字符串和另外一个字符串进行匹配。算法
BF 算法中的 BF 是 Brute Force 的缩写,中文叫做暴力匹配算法,也加朴素匹配算法。从名字能够看出,这种方法很暴力,效率也不高,可是简单、好懂。数组
在要匹配的两个字符串中,一个称之为主串,一个称之为模式串。好比要在字符串中 A 中查找字符串 B,那么字符串 A 就是主串,字符串 B 就是模式串。子串的长度为 n,模式串的长度为 m,由于要在主串中查找模式串,因此有 n>m。数据结构
BF 算法的思想很简单,就是拿主串中起始位置分别为 长度为 m 的总共 n-m+1 个子串分别与模式串进行比较,看有没有能匹配上的。函数
能够看到,每次咱们都要比较 m 个字符,极端状况下总共要比较 n-m+1 次,因此算法的最坏状况时间复杂度为 O(m*n)。.net
能够看到,这个算法的时间复杂度很高,但在实际的开发中,它倒是一个比较经常使用的字符串匹配算法。一者由于实际开发中两个字符串的长度都不会太长,并且也不会每次都须要比较 n-m+1 次;两者由于其算法实现起来很是简单,不容易出错,便于维护。这也就是咱们常说的 KISS(Keep it Simple and Stupid) 原则。设计
RK 算法的全称叫做 Rabin-Karp 算法,是为了记念它的两个发明者而这样命名的。 这个算法其实就是刚刚 BF 算法的升级版。3d
在 BF 算法中,每次都要对 m 个字符逐个进行比较,这就大大下降了算法的效率。这时候,咱们引入哈希算法,对子串逐个求哈希值,而后与模式串的哈希值进行比较来判断两个子串是否匹配。在不考虑哈希冲突的状况下,数字之间的比较就很是快了。cdn
可是,在计算子串哈希值的时候,咱们依然须要遍历 m 个字符,算法总体的效率并无提升。咱们须要设计一个特殊的哈希函数来避免每次都要遍历 m 个字符,这样,算法的效率就会大大改善。blog
对此,咱们将包含 K 个字符的子串用一个 K 进制数来表示,将这个 K 进制数转化为 10 进制数做为子串的哈希值。好比字符串都是由小写字母组成,那么 a-z 这 26 个字母就映射到 0-25,0 表示 a,1 表示 b,以此类推。将 K 进制的数转化为 10 进制只须要将 10 变为 K 便可,以下图所示。开发
这样计算哈希值的话相邻两个子串就有必定关系。
假设 、
分别是起始位置为
和
的哈希值,而
为位置为
处字符的的映射,那么就有:
其中 这个指数项能够事先计算出来放在一个数组中,当咱们须要的时候,就从对应下标中取出来便可。
能够看到,计算哈希值的时候,咱们只须要遍历一次主串便可计算出全部子串的哈希值,这部分时间复杂度为 O(n)。模式串和子串须要比较 n-m+1 次哈希值,这部分时间复杂度也为 O(n)。因此,RK 算法总的时间复杂度为 O(n)。
可是,若是模式串的长度很大,那么计算出来的哈希值就会超出计算机中整形数据能够表示的范围。这时候,咱们就能够牺牲一下,容许出现哈希冲突,好比能够求全部字符的映射和等,这种状况下哈希值的范围就小不少了。此时,当两个子串哈希值相同时,咱们须要再进一步肯定两者自己是不是相同的。
获取更多精彩,请关注「seniusen」!