BMM算法,逆向最大匹配法(backward maximum matching method, BMM),和FMM一样,都是基于词表的分词方法。
与FMM不同的是,BMM是对于一段文本从右至左进行扫描,利用词典里面的词汇切分出长度最长的词,也就是说文本扫描的方式刚好与FMM相反。分词效果相对FMM来说,BMM算法更好。

以下是简单实现

<?php

class BMM
{

    //简单定义一个词典数组
    private $dict = [];
    private $result = []; //结果集

    // 是否为词典中的词
    private function  inDict($str)
    {
        $flag = false;
        //遍历整个词典
        for ($i = 0; $i < count($this->dict); $i++) {
            // 是否有词典相等的词
            if ($str == $this->dict[$i]) {
                $flag = true;
                break;
            }
        }
        return $flag;
    }

    public function loadDict(array $array)
    {
        $this->dict = $array;
    }

    /**
     * @param $sentence 要匹配的句子
     * @param $matchWordLength 匹配词组的最大长度 
     * 要确认这个值要大于等于你字典长度最长词的长度
     * 超过这个长度的词无法正确匹配
     */
    public function split($sentence, $matchWordLength = 6)
    {
        $this->result = []; //重置结果集
        $sentenceLength = mb_strlen($sentence); //计算句子长度
        for ($i = 0; $i < $sentenceLength;) {
            //计算截取词的长度
            if ($sentenceLength - $i < $matchWordLength) {
                $matchWordLength = $sentenceLength - $i;
            }
            //计算截取字符串的偏移量
            $strBegin = $sentenceLength - $i - $matchWordLength;
            // 截取的要处理的子句子
            $subSentence = mb_substr($sentence, $strBegin, $matchWordLength);
            //拆分子句子的词
            for ($j = 0; $j < $matchWordLength; $j++) {
                $k = $matchWordLength - $j;
                //切出词
                $tmp = mb_substr($subSentence, $j, $k);
                //如果词典有该词或者是单词
                if ($this->inDict($tmp) || $j == $matchWordLength - 1) {
                    $this->result[] = $tmp;
                    $i = $i + $k; //修改偏移量
                    break;
                }
            }
        }
        //因为切换是从右至左,所以倒序一下
        krsort($this->result);
    }

    public function getResultText()
    {
        return implode(" \ ", $this->result);
    }
}

使用方式

$BMM = new BMM();
$BMM->loadDict(['的确', '王公', '实在', '在理', '公子', '确实']);
$BMM->split('王公子说的确实在理');
echo $BMM->getResultText() . "\n";

实际效果

王 公子 说 的 确实 在理

实际效果会比FMM效果好些