Posts tagged ‘中文分词’

SCWS是一款简单的开源中文分词系统,其网址为:http://www.ftphp.com/scws/

在代码中添加了一些输出,以便探究其分词的算法:

[yicheng@chengyi cli]$ ./scws -c utf-8 -d dict.utf8.xdb -r rules.utf8.ini -D -i ‘中国人民在中国人民大学上大学’ -t 10
No. WordString               Attr  Weight(times)
————————————————-
[0,0]Ox11(中)
[0,1]Ox83(中国)
[0,2]Ox81(中国人)
[1,1]Ox31(国)
[1,2]Ox81(国人)
[2,2]Ox31(人)
[2,3]Ox81(人民)
[3,3]Ox21(民)
[4,4]Ox1(在)
[5,5]Ox11(中)
[5,6]Ox83(中国)
[5,7]Ox83(中国人)
[5,10]Ox81(中国人民大学)
[6,6]Ox31(国)
[6,7]Ox81(国人)
[7,7]Ox31(人)
[7,8]Ox83(人民)
[7,10]Ox81(人民大学)
[8,8]Ox21(民)
[9,9]Ox31(大)
[9,10]Ox81(大学)
[10,10]Ox21(学)
[11,11]Ox1(上)
[12,12]Ox11(大)
[12,13]Ox81(大学)
[13,13]Ox21(学)
PATH by keyword = 中国人, (weight=8.9964):
中国人 民
PATH by keyword = 中国, (weight=219.7764):
中国 人民
PATH by keyword = 国人, (weight=0.0218):
中 国人 民
PATH by keyword = 人民, (weight=219.7764):
中国 人民
01. 中国人民大学       nt    10.64(1)
02. 中国                   ns    6.26(1)
03. 人民                   n     4.41(1)
04. 大学                   n     4.23(1)
+–[lt-scws(scws-cli/1.1.2)]———-+
| TextLen:   42                  |
| Prepare:   0.0074    (sec)     |
| Segment:   0.0010    (sec)     |
+——————————–+

以下简单记录今天看代码的收获。

typedef struct

{

xdict_t d;

rule_t r;

unsigned char *mblen;

unsigned int mode;

unsigned char *txt;

int zis;

int len;

int off;

int wend;

scws_res_t res0;

scws_res_t res1;

word_t **wmap;

struct scws_zchar *zmap;

}       scws_st, *scws_t;

是很核心的结构体。其中,使用txt保存用户输入的待分词字符串,使用off记录当前待处理的字节位置,res0为返回的分词结果,wmap就是上面输出的二维数组,zmap为wmap中每个词在txt中的index位置,d是字典,r是rule。

1、在scws_get_result函数中,首先按照最简单的规则,对文字进行分段,比如字母、数字、标点、换行符等,都被当做token来分段。

2、 对于每一段,首先初始化wmap二维数组,在它的对角线上存储每个字。

3、 然后依次访问wmap的对角线,向后匹配,在字典中查找,若找到匹配结果,则存储在wmap的行里。比如

[0,0]Ox11(中)
[0,1]Ox83(中国)
[0,2]Ox81(中国人)

就是从对角线的第一个元素,依次匹配第二个、第三个元素的结果。

4、 根据rule,进行规则过滤

5、 对wmap中的元素遍历,根据tf、idf计算weight,找出weight最大的path,作为最优分词结果。

6、 清理内存,返回。

scws_get_result的返回结果是二维的。每一次返回的是当前段的处理结果,是一个链表。该结果的next,是下一段的处理结果。

所以需要

while (res = cur = scws_get_result(s))

{

while (cur != NULL)

{

printf(“Word: %.*s/%s (IDF = %4.2f)\n”,

cur->len, text+cur->off, cur->attr, cur->idf);

cur = cur->next;

}

scws_free_result(res);

printf(“\n———————\n”);

}