PHP实现支持中文的字典树

字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

1. 辅助函数,字符串拆分函数,这个是借鉴了网上的函数,支持中文utf-8的字符串

/*
    将可能含有中文的字符串进行拆分,如 “我爱北京” 转换成 array("我","爱","北","京")
*/
function str_split_utf8($str)
{
    $split = 1;
    $array = array();
    for ($i = 0; $i < strlen($str);) {
        $value = ord($str[$i]);
        if ($value > 127) {
            if ($value >= 192 && $value <= 223) {
                $split = 2;
            } elseif ($value >= 224 && $value <= 239) {
                $split = 3;
            } elseif ($value >= 240 && $value <= 247) {
                $split = 4;
            }
        } else {
            $split = 1;
        }
        $key = null;
        for ($j = 0; $j < $split; $j++, $i++) {
            $key .= $str[$i];
        }
        array_push($array, $key);
    }
    return $array;
}


数组切分函数
/*
    切分数组
*/
function retSubArray($array,$start,$end)
{
    $retArray = array();
    $count = 0;
    foreach($array as $v)
    {
        if($count >= $end) break; 
        if($count >= $start )
        {
            $retArray[] = $v;
        }
        $count++;
    }
    return $retArray;
}

2. 字典树构建函数

/*
    递归的将str_split_utf8生成的数组查到字典树中
*/
function mkMapSub($wordArray, &$mapSubArray)
{
    $length = count($wordArray);
    if ($length > 0) {
        // 取出第一个字
        $word = $wordArray[0];
        // 查看字典树中是否匹配第一个字,没有的话就插入这个字
        if (!isset($mapSubArray[$wordArray[0]])) {
            $mapSubArray[$wordArray[0]] = array();
        }
        if($length == 1)
        {// 只有一个字,就插入一个结束标识
            $mapSubArray[$wordArray[0] . "end"] = 1;
        }
        // 已经插入的字出栈
        array_shift($wordArray);
        // 递归插入
        mkMapSub($wordArray, $mapSubArray[$word]);
    }
}

3. 查找函数

全词匹配

/*
    递归查询词是否在字典树中
*/
function wordInMap($str, &$map)
{
    if (count($str) == 1) {
        // 一个字的情况
        if (isset($map[$str[0]]) && $map[$str[0]] == array()) 
        { 
            return true;
        } else {  
        if( isset($map[$str[0] . "end"]) && $map[$str[0] . "end"] == 1 )
        {  
            return true;
        }
            return false;
        }
    } else {
        // 按字递归查找
        $word = array_shift($str);
        if (isset($map[$word])) { 
            return wordInMap($str, $map[$word]);
        } else {
            return false;
        }
    }
}

句子切词查找


/*
    查找一个句子中是否在字典树中有词命中
*/
function longStrInMap($str, &$map)
{
    if(wordInMap($str,$map))
    {
        return array($str);
    }
    $strArray = str_split_utf8($str);
    $length = count($strArray);
    $hasList = array();
    for ($index = 0; $index < $length; $index++) {
        $word = $strArray[$index];
        if (isset($map[$word])) 
        {
            //尝试测试子数组
            for ($subIndex = $index; $subIndex <= $length; $subIndex++)
            {
                $subStr = retSubArray($strArray,$index,$subIndex); 
                if(wordInMap($subStr,$map))
                {
                    $hasList[] = $subStr;
                }
            }
        }
    } 
    $retArray = array();
    foreach($hasList as $v)
    {
        $retArray[] = implode("",$v);
    }
    return $retArray;
}

4. 入口函数

/*
    从源文件中读取数据
*/
$words = array();
$sAllMapDatas = file_get_contents("maplist");
$aAllMapDatas = explode("\n",$sAllMapDatas);
foreach($aAllMapDatas as $vDatas)
{
    $words[] = trim($vDatas);
}

// 根据词表建立map
$map = array();
foreach ($words as $vWord) {  
      $wordArray = str_split_utf8($vWord);
        mkMapSub($wordArray, $map);  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值