字符串匹配KMP算法
By skyshappiness Posted 2017-03-30 12:30:47 In

一、简介:

      KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。


二、原理:

      字符串: ABCBAACEDCBABADB

      搜索串: BABAD


一、计算搜索串部分匹配表

      ---- B 的前缀和后缀为空                                                         0

      ---- BA 前缀 B 后缀 A    交集为空                                             0

      ---- BAB 前缀 B BA 后缀 AB B交集为 B                                       1

      ---- BABA 前缀 B BA BAB 后缀 ABA BA A  交集为 BA                     2

      ---- BABAD 前缀 B BA BAB BABA 后缀 ABAD BAD AD D 交集为空     0


二、匹配计算

      1、ABCBAACEDCBABADB

            BABAD

       2、ABCBAACEDCBABADB

               BABAD                                           位移步数 = 已匹配字符数 - 对应匹配字符数 = 1 - 0 = 1

       3、ABCBAACEDCBABADB

                 BABAD 

       4、ABCBAACEDCBABADB

                   BABAD                                        位移步数 = 已匹配字符数 - 对应匹配字符数 = 2 - 0 = 2

       5、ABCBAACEDCBABADB

                        BABAD                                  此处一直后移一位,直至情况 6 出现

       6、ABCBAACEDCBABADB

                                   BABAD                            


三、程序语言:

    public function testKMP(){
        $be_search_str = 'ABCBAACEDCBABADB';
        $search_str = 'CBAA';
        $match_table = $this->_calculateMatchTable($search_str);
        $be_search_len = strlen($be_search_str);
        $search_len = strlen($search_str);
        for($i = 0; $i < $be_search_len; $i++){
            $j = 0;
            for($j = 0; $j < $search_len; $j++){
                $first_compare_word = substr($be_search_str, ($i+$j), 1);
                $compare_word = substr($search_str, $j, 1);
                if($first_compare_word === $compare_word){
                    if($j === ($search_len - 1) ){ echo ($i); exit; }
                    $step_value = $j - $match_table[($j-1)];
                }else{
                    if($step_value > 0){
                        $i = $i + $step_value;
                        $step_value = 0;
                    }
                    break;
                }
            }
        }
    }
    
    /**
     * 计算部分匹配表
     * @param type $search_str
     * @return boolean|int
     */
    private function _calculateMatchTable($search_str = ''){
        if($search_str == ''){ return FALSE; }
        $result = array();
        $result[] = 0;
        $str_len = strlen($search_str);
        if($str_len == 1){ return $result; }
        for($i = 2; $i <= $str_len; $i++){
            $calculate_str = substr($search_str, 0, $i);
            $calculate_count = 0;
            for($j = 1; $j < $i; $j++){
                $front_str = substr($search_str, 0, $j);
                $end_str = substr($search_str, (strlen($calculate_str) - $j), $j);
                if($front_str === $end_str){
                    $calculate_count += strlen($front_str);
                }
            }
            $result[] = $calculate_count;
        }
        return $result;
    }

友情链接
联系方式
  • 邮箱 / E-mail:121388038@qq.com