我们先说下定义,比如说我们要在a字符串中查找字符串b,那么a就是主串,b就是模式串
我们把主串的长度记为n,把模式串的长度记为m,n>m
BF(Brute Force)中文名:暴力匹配算法,朴素匹配算法
简单的说BF的算法就是在主串中查找起始位置是0,1,2,,,n-m个且长度为m的n-m+1个子串,看看有没有跟模式串匹配的
如下图所示
下面是我用php实现的BF算法的代码,很简单
function BFString($mainString = 'abcdefghijklmn', $patternString = 'lmn') { //主串长度 $n = strlen($mainString); //模式串长度 $m = strlen($patternString); //需要匹配的次数 $needMatchCount = $n - $m + 1; //真实匹配的次数 $trueMatchCount = 0; //是否匹配到 $isMatch = false; for ($i = 0; $i <= $needMatchCount; $i++) { $nowString = substr($mainString, $i, $m); if ($patternString == $nowString) { $isMatch = true; $trueMatchCount = $i; break; } } return ['isMatch' => $isMatch, 'trueMatchCount' => $trueMatchCount]; }
这种算法的时间复杂度是O(n*m),可以看出来很暴力,但是实际运用中,这种算法用的还是很多的
原因:
1:实现起来简单,出bug以后容易修复
2:实际软件开发中,主串和模式串的长度都不会很长,而且在匹配中当模式串遇到不能匹配的字符时就停止了,不需要把m个字符都匹配
字符串匹配算法RK(Rabin-Karp)算法
这个算法的核心就是计算出模式串的哈希值,然后依次和主串中每个子串的哈希值进行比较
因为哈希值计算出来的是数字,数字和数字比较速度会比字符串和字符串比较速度快
所以说这个算法就是BF算法的改进版
实现代码如下
/** * 字符串匹配算法RK(Rabin-Karp)算法 */ function RKString($mainString, $patternString) { //主串长度 $n = strlen($mainString); //模式串长度 $m = strlen($patternString); //需要匹配的次数 $needMatchCount = $n - $m + 1; //需要匹配的字符的哈希值 $patternStringHash = self::RKStringHash($patternString); //真实匹配的次数 $trueMatchCount = 0; //是否匹配到 $isMatch = false; for ($i = 0; $i <= $needMatchCount; $i++) { $nowString = substr($mainString, $i, $m); $nowStringHash = self::RKStringHash($nowString); //因为哈希算法可能有冲突,所以这里多加了一个$patternString == $nowString判断条件 if ($patternStringHash == $nowStringHash && $patternString == $nowString) { $isMatch = true; $trueMatchCount = $i; break; } } return ['isMatch' => $isMatch, 'trueMatchCount' => $trueMatchCount, 'nowString' => $nowString, 'nowStringHash' => $nowStringHash]; } /** * 字母转成26进制(哈希) * @param $num * @param int $bin * @return float|int */ public static function RKStringHash($string, $bin = 26) { $arr = self::BIN_TODEC_DATA; if ($bin == 10) return $string; //为10进制不转换 $atnum = str_split($string); //将字符串分割为单个字符数组 $atlen = count($atnum); $total = 0; $i = 1; foreach ($atnum as $tv) { $tv = strtoupper($tv); if (array_key_exists($tv, $arr)) { if ($arr[$tv] == 0) continue; $total = $total + $arr[$tv] * pow($bin, $atlen - $i); } $i++; } return $total; }
了解更多:https://www.toutiao.com/c/user/83293539887/#mid=1633933053814798