IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

基于trie数据字典的php中文分词

排头兵 @ Talk 2010-07-21 09:52:25 累计浏览 3,912 次
本机暂存

    keywords:中文分词、PHP中文分词、trie数据结构、Doubule Array Trie Datastruct

    原理:

    Trie数据结构的名词介绍我就不介绍了,大家google,百度可以搜索一大堆的文章来.

    Tire索引树法

    结构:首字散列表、Trie索引树结点

    优点:分词中,不需预知待查询词的长度,沿树链逐字匹配。

    缺点:构造和维护比较复杂,单词树枝多,浪费了一定的空间。

    有时间我会写一个双数组trie的中文分词小程序来,下面来最简单的trie,

    代码:

以下是代码片段:
< ?php 
/** 
 * @version 0.1 
 * @todo 构造通用的字典算法,并写了一个简易的分词 
 * @author shjuto@gmail.com 
 * Trie字典树 
 * 
 */ 
class Trie 

    private $trie;  
  
    function __construct() 
    { 
         $trie = array(’children’ => array(),’isword’=>false); 
    } 
  
    /** 
     * 把词加入词典 
     * 
     * @param String $key 
     */ 
    function &setWord($word=’’) 
    { 
        $trienode = &$this->trie; 
        for($i = 0;$i < strlen($word);$i++) 
        { 
            $character = $word[$i]; 
            if(!isset($trienode[’children’][$character])) 
            { 
                $trienode[’children’][$character] = array(’isword’=>false); 
            } 
            if($i == strlen($word)-1) 
            { 
                    $trienode[’children’][$character] = array(’isword’=>true); 
            } 
            $trienode = &$trienode[’children’][$character]; 
        } 
    } 
  
    /** 
     * 判断是否为词典词 
     * 
     * @param String $word 
     * @return bool true/false 
     */ 
    function & isWord($word) 
    { 
        $trienode = &$this->trie; 
        for($i = 0;$i < strlen($word);$i++) 
        { 
            $character = $word[$i]; 
            if(!isset($trienode[’children’][$character])) 
            { 
                return false; 
            } 
            else  
            { 
                //判断词结束 
                if($i == (strlen($word)-1) && $trienode[’children’][$character][’isword’] == true) 
                { 
                    return true; 
                } 
                elseif($i == (strlen($word)-1) && $trienode[’children’][$character][’isword’] == false) 
                { 
                    return false; 
                } 
                $trienode = &$trienode[’children’][$character];     
            } 
        } 
    } 
  
       /** 
     * 在文本$text找词出现的位置 
     * 
     * @param String $text 
     * @return array array(’position’=>$position,’word’ =>$word); 
     */ 
    function search($text="") 
    { 
        $textlen = strlen($text); 
        $trienode = $tree = $this->trie; 
        $find = array(); 
        $wordrootposition = 0;//词根位置 
        $prenode = false;//回溯参数,当词典ab,在字符串aab中,需要把$i向前回溯一次 
        $word = ’’; 
        for ($i = 0; $i < $textlen;$i++) 
        { 
  
            if(isset($trienode[’children’][$text[$i]])) 
            { 
                $word = $word .$text[$i]; 
                $trienode = $trienode[’children’][$text[$i]]; 
                if($prenode == false) 
                { 
                    $wordrootposition = $i; 
                } 
                $prenode = true; 
                if($trienode[’isword’]) 
                { 
                    $find[] = array(’position’=>$wordrootposition,’word’ =>$word); 
                } 
            } 
            else  
            { 
                $trienode = $tree; 
                $word = ’’; 
                if($prenode) 
                { 
                    $i = $i -1; 
                    $prenode = false; 
                } 
            } 
        } 
        return $find; 
    } 

$trie = new Trie(); 
$trie->setWord(’中国’); 
$trie->setWord(’中国人’); 
$trie->setWord(’伟大’); 
$trie->setWord(’军队’); 
$trie->setWord(’中国人民’); 
$trie->setWord(’中国人民解放军’); 
$trie->setWord(’解放军’); 
$trie->setWord(’解放’); 
$words = $trie->search(’伟大的中国人民解放军解放了全中国,是很伟大的军队’); 
foreach ($words as $word) 

    echo ’位置:’.$word[’position’].’-’.(strlen($word[’word’])+$word[’position’]); 
    echo ’  词:’.$word[’word’]."\n"; 
}

    运行结果:

    位置:0-6 词:伟大

    位置:9-15 词:中国

    位置:9-18 词:中国人

    位置:9-21 词:中国人民

    位置:9-30 词:中国人民解放军

    位置:30-36 词:解放

    位置:42-48 词:中国

    位置:55-61 词:伟大

    位置:64-70 词:军队

    ―――――――――――――――――――――――

    以前研究过分词的人,很容易发现这个分词还是不足的,但是对于想了解中文分词的基本原理的同学可以思考一下。

    分词结果不够准确,解放军都没有分出来,原因嘛,是最大匹配中国人民解放军以后,我直接把$word轻松了,你可以修改search函数的代码

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,270)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,408)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,150)
  5. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,790)
  6. 15个最好的免费开源电子商务平台 (累计阅读 12,541)
  7. Redis消息队列的若干实现方式 (累计阅读 12,088)
  8. 到底什么是MVC? (累计阅读 11,869)
  9. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,709)
  10. Rolling cURL: PHP并发最佳实践 (累计阅读 11,488)