您的位置:首页 > 编程语言 > PHP开发

PHP实现支持中文的字典树

2014-10-24 16:33 232 查看
字典树又称单词查找树,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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索引擎 递归 php