FMM算法,即正向最大匹配法(forward maximum matching method, FMM),是基于词表的分词方法。
对于一段文本从左至右进行扫描,利用词典里面的词汇切分出长度最长的词,单词的颗粒度越大,所能表示的含义越确切。

以下简单实现

<?php
class FMM
{

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

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

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


    public function split($sentence)
    {
        $this->result = []; //重置结果集
        $wordlen = 1; //切分词的长度
        $s1 = ""; //匹配出的字符串
        //从左到右扫描字符串
        for ($i = 0; $i < mb_strlen($sentence); $i = $i + $wordlen) {
            //切出部分待验证的字符串
            $tmp = $s1 . mb_substr($sentence, $i, $wordlen);

            if ($this->inDict($tmp)) {
                //将匹配到的词放入$1并继续匹配,因为要确保匹配出的词为最大匹配
                $s1 = $tmp;
            } else {
                //如果找不到,则将当前匹配的字符串作为结果
                $this->result[] = $s1;
                //同时从下一个词开始切新词
                $s1 = mb_substr($sentence, $i, $wordlen);
            }
        }
        //将剩下来未匹配的词也加入进来
        $this->result[] = $s1;
    }

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

使用方式

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

效果
王公 子 说 的确 实在 理

接下来可以看看下篇关于BMM分词的效果