• 字符串匹配算法


    我们先说下定义,比如说我们要在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

  • 相关阅读:
    生成不带签名(BOM)的UTF8格式的XML
    矢量数据的裁剪及合并
    使用dotNET_Reactor4.7加密后的dll在VS2010中无法打包
    加密后的程序在Win8中无法运行
    修改jpg的图片大小
    shapefile中dbf的数据格式(转载)
    shapefile 输出的地理处理注意事项(转载)
    linxu下面的绝对路径和相对路径
    go中的类型转换成interface之后如何复原
    使用docker部署一个go应用
  • 原文地址:https://www.cnblogs.com/sjks/p/10898672.html
Copyright © 2020-2023  润新知