日志
英文无空格分词函数
发布者:星野天河 发布时间:08-06-04
查看次数:54 评论数:0
标签:函数(3) pspell(2) 域名(2) aspell(1) 分词(1)
英文无空格分词函数
最近做一个计算过期域名重要性排序的应用,主要的难题是英文的分词问题,因为普通的英文基本上按空格切就行了,而域名各词之间没有空格.
本来要用aspell和pspell扩展的,都安装好了并且也可以自己加词,可惜不知道怎么把原词典去除(因为客户需要完全自定义词典).后来算了还是用php+mysql自己来吧.
下面是简单的分词函数.$dict是数据库的输出
PHP代码
- /**
- *简单切词.取大优先,从后匹配起.例如theman 是the man而不是them an
- * 计算词得分
- *
- * @param str $word 要计算的词
- * @param array $words 一维索引数组. array(0=>'word')形式
- * @param array $scores 一维关联数组 array('word'=>24)形式
- * @return int
- */
- function cutWord($word, $dict=array(), $ini=false)
- {
- //初始化
- static $curr; //当前判断的词
- static $words; //词库
- static $rs; //分词结果
- if($ini) {
- $curr = null; $words = null; $rs = null;
- }
- if(!$curr) {
- $word = strtolower(str_replace(array('-', '_'), '', $word));
- $curr = $word; //记录初始字符串
- }
- if(!$words) $words = $dict;
- if(!$rs) $rs = array();
- //判断开始
- if(in_array($word, $words)) {
- $rs[] = $word;
- $curr = str_replace($word, '', $curr); //成功后减去已经匹配子串,再重新切
- if($curr) cutWord($curr);
- }elseif(strlen($word) > 1){
- cutWord(substr($word, 1, 999));
- }else{
- $curr = substr($curr, 0, -1); //失败后减1
- if(!$curr) return $rs;
- cutWord($curr);
- }
- return $rs;
- }
原理如下
假设theboy这个词,先测试theboy是否一个完整的词,如果不完全再测试heboy依此类推,直到匹配了boy,然后theboy这个词去除己匹配的boy,再新测试剩余的the字符串,再次通过。结果输出
array('the', 'boy')数组。
另外如果是theboya的情况,匹配到最后a仍然不是词,此时要减去最后字符(如本例匹配theboy),一个个减直到减没了输出结果。
初始词,词库,分词结果都利用了PHP函数的静态变量特性,除了首次赋值,以后再运行函数变量值还存在。(有点类的味道),这样不用把那么大的词典参数传来传去的会快些。)
最后测试几十个域名(一般每天就这么多),词量一千多的情况下运行时间7毫秒,这还加上了长度加权,正则加权,类型加权这些加权法。
要是早自己做这个项目肯定三天搞定,也不知道为啥当初要找什么PHP扩展,不但自己安装调试麻烦而且到时候还不定能顺利装到客户的服务器上。可能当时觉得“分词”这种事用PHP做肯定很慢吧,不过词典自定义,并且域名列表小的话,程序再优化些真的完全够用了。
评论列表
评论表单
妮称

