几个月之前,在网上找到了一个中文词库素材(几百K),当时便想写一个分词程序了.我对汉语分词没有什么研究,也就凭自己臆想而写.若有相关方面专家,还请多给意见.
一、词库
一、词库
词库大概有5万多词语(google能搜到,类似的词库都能用),我摘要如下:
地区
82
重要 81
新华社 80
技术 80
会议 80
自己 79
干部 78
职工 78
群众 77
没有 77
今天 76
同志 76
部门 75
加强 75
组织 75
重要 81
新华社 80
技术 80
会议 80
自己 79
干部 78
职工 78
群众 77
没有 77
今天 76
同志 76
部门 75
加强 75
组织 75
第一列是词,第二列是权重.我写的这个分词算法目前并未利用权重.
二、设计思路
算法简要描述:
对一个字符串S,从前到后扫描,对扫描的每个字,从词库中寻找最长匹配.比如假设S="我是中华人民共和国公民",词库中有"中华人民共和国","中华","公民","人民","共和国"......等词.当扫描到"中"字,那么从中字开始,向后分别取1,2,3,......个字("中","中华","中华人","中华人民","中华人民共","中华人民共和","中华人民共和国",,"中华人民共和国公"),词库中的最长匹配字符串是"中华人民共和国",那么就此切分开,扫描器推进到"公"字.
数据结构:
选择什么样的数据结构对性能影响很大.我采用Hashtable _rootTable记录词库.键值对为(键,插入次数).对每一个词语,如果该词语有N个字,则将该词语的1,1~2,1~3,......1~N个字作为键,插入_rootTable中.而同一个键如果重复插入,则后面的值递增.
三、程序
具体程序如下(程序中包含权重,插入次数等要素,目前的算法并没有利用这些.可以借此写出更有效的分词算法):
ChineseWordUnit.cs //struct--(词语,权重)对
1
public
struct
ChineseWordUnit
2 {
3privatestring_word;
4privateint_power;
5
6/**////<summary>
7///中文词语单元所对应的中文词。
8///</summary>
9publicstringWord
10{
11get
12{
13return_word;
14}
15}
16
17/**////<summary>
18///该中文词语的权重。
19///</summary>
20publicintPower
21{
22get
23{
24return_power;
25}
26}
27
28/**////<summary>
29///结构初始化。
30///</summary>
31///<paramname="word">中文词语</param>
32///<paramname="power">该词语的权重</param>
33publicChineseWordUnit(stringword,intpower)
34{
35this._word=word;
36this._power=power;
37}
38}
2 {
3privatestring_word;
4privateint_power;
5
6/**////<summary>
7///中文词语单元所对应的中文词。
8///</summary>
9publicstringWord
10{
11get
12{
13return_word;
14}
15}
16
17/**////<summary>
18///该中文词语的权重。
19///</summary>
20publicintPower
21{
22get
23{
24return_power;
25}
26}
27
28/**////<summary>
29///结构初始化。
30///</summary>
31///<paramname="word">中文词语</param>
32///<paramname="power">该词语的权重</param>
33publicChineseWordUnit(stringword,intpower)
34{
35this._word=word;
36this._power=power;
37}
38}
ChineseWordsHashCountSet.cs //词库容器
1
/**/
///<summary>
2///记录字符串出现在中文字典所录中文词语的前端的次数的字典类。如字符串“中”出现在“中国”的前端,则在字典中记录一个次数。
3///</summary>
4 public class ChineseWordsHashCountSet
5 {
6/**////<summary>
7///记录字符串在中文词语中出现次数的Hashtable。键为特定的字符串,值为该字符串在中文词语中出现的次数。
8///</summary>
9privateHashtable_rootTable;
10
11/**////<summary>
12///类型初始化。
13///</summary>
14publicChineseWordsHashCountSet()
15{
16_rootTable=newHashtable();
17}
18
19/**////<summary>
20///查询指定字符串出现在中文字典所录中文词语的前端的次数。
21///</summary>
22///<paramname="s">指定字符串</param>
23///<returns>字符串出现在中文字典所录中文词语的前端的次数。若为-1,表示不出现。</returns>
24publicintGetCount(strings)
25{
26if(!this._rootTable.ContainsKey(s.Length))
27{
28return-1;
29}
30Hashtable_tempTable=(Hashtable)this._rootTable[s.Length];
31if(!_tempTable.ContainsKey(s))
32{
33return-1;
34}
35return(int)_tempTable[s];
36}
37
38/**////<summary>
39///向次数字典中插入一个词语。解析该词语,插入次数字典。
40///</summary>
41///<paramname="s">所处理的字符串。</param>
42publicvoidInsertWord(strings)
43{
44for(inti=0;i<s.Length;i++)
45{
46string_s=s.Substring(0,i+1);
47this.InsertSubString(_s);
48}
49}
50
51/**////<summary>
52///向次数字典中插入一个字符串的次数记录。
53///</summary>
54///<paramname="s">所插入的字符串。</param>
55privatevoidInsertSubString(strings)
56{
57if(!_rootTable.ContainsKey(s.Length)&&s.Length>0)
58{
59Hashtable_newHashtable=newHashtable();
60_rootTable.Add(s.Length,_newHashtable);
61}
62Hashtable_tempTable=(Hashtable)_rootTable[s.Length];
63if(!_tempTable.ContainsKey(s))
64{
65_tempTable.Add(s,1);
66}
67else
68{
69_tempTable[s]=(int)_tempTable[s]+1;
70}
71}
72}
2///记录字符串出现在中文字典所录中文词语的前端的次数的字典类。如字符串“中”出现在“中国”的前端,则在字典中记录一个次数。
3///</summary>
4 public class ChineseWordsHashCountSet
5 {
6/**////<summary>
7///记录字符串在中文词语中出现次数的Hashtable。键为特定的字符串,值为该字符串在中文词语中出现的次数。
8///</summary>
9privateHashtable_rootTable;
10
11/**////<summary>
12///类型初始化。
13///</summary>
14publicChineseWordsHashCountSet()
15{
16_rootTable=newHashtable();
17}
18
19/**////<summary>
20///查询指定字符串出现在中文字典所录中文词语的前端的次数。
21///</summary>
22///<paramname="s">指定字符串</param>
23///<returns>字符串出现在中文字典所录中文词语的前端的次数。若为-1,表示不出现。</returns>
24publicintGetCount(strings)
25{
26if(!this._rootTable.ContainsKey(s.Length))
27{
28return-1;
29}
30Hashtable_tempTable=(Hashtable)this._rootTable[s.Length];
31if(!_tempTable.ContainsKey(s))
32{
33return-1;
34}
35return(int)_tempTable[s];
36}
37
38/**////<summary>
39///向次数字典中插入一个词语。解析该词语,插入次数字典。
40///</summary>
41///<paramname="s">所处理的字符串。</param>
42publicvoidInsertWord(strings)
43{
44for(inti=0;i<s.Length;i++)
45{
46string_s=s.Substring(0,i+1);
47this.InsertSubString(_s);
48}
49}
50
51/**////<summary>
52///向次数字典中插入一个字符串的次数记录。
53///</summary>
54///<paramname="s">所插入的字符串。</param>
55privatevoidInsertSubString(strings)
56{
57if(!_rootTable.ContainsKey(s.Length)&&s.Length>0)
58{
59Hashtable_newHashtable=newHashtable();
60_rootTable.Add(s.Length,_newHashtable);
61}
62Hashtable_tempTable=(Hashtable)_rootTable[s.Length];
63if(!_tempTable.ContainsKey(s))
64{
65_tempTable.Add(s,1);
66}
67else
68{
69_tempTable[s]=(int)_tempTable[s]+1;
70}
71}
72}
ChineseParse.cs //分词器
1
/**/
///<summary>
2///中文分词器。
3///</summary>
4 public class ChineseParse
5 {
6privatestaticChineseWordsHashCountSet_countTable;
7
8staticChineseParse()
9{
10_countTable=newChineseWordsHashCountSet();
11InitFromFile("ChineseDictionary.txt");
12}
13
14/**////<summary>
15///从指定的文件中初始化中文词语字典和字符串次数字典。
16///</summary>
17///<paramname="fileName">文件名</param>
18privatestaticvoidInitFromFile(stringfileName)
19{
20stringpath=Directory.GetCurrentDirectory()+@"\"+fileName;
21if(File.Exists(path))
22{
23using(StreamReadersr=File.OpenText(path))
24{
25strings="";
26while((s=sr.ReadLine())!=null)
27{
28ChineseWordUnit_tempUnit=InitUnit(s);
29_countTable.InsertWord(_tempUnit.Word);
30}
31}
2///中文分词器。
3///</summary>
4 public class ChineseParse
5 {
6privatestaticChineseWordsHashCountSet_countTable;
7
8staticChineseParse()
9{
10_countTable=newChineseWordsHashCountSet();
11InitFromFile("ChineseDictionary.txt");
12}
13
14/**////<summary>
15///从指定的文件中初始化中文词语字典和字符串次数字典。
16///</summary>
17///<paramname="fileName">文件名</param>
18privatestaticvoidInitFromFile(stringfileName)
19{
20stringpath=Directory.GetCurrentDirectory()+@"\"+fileName;
21if(File.Exists(path))
22{
23using(StreamReadersr=File.OpenText(path))
24{
25strings="";
26while((s=sr.ReadLine())!=null)
27{
28ChineseWordUnit_tempUnit=InitUnit(s);
29_countTable.InsertWord(_tempUnit.Word);
30}
31}