简单实用的C#分词源代码(含词库素材下载)

本文介绍了一种基于词库的中文分词算法的设计思路与实现细节,包括使用Hashtable存储词频信息、通过逐字匹配实现最长词优先分词等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、词库

词库大概有5万多词语(Google能搜到,类似的词库都能用),我摘要如下:

地区 82
重要 81
新华社 80
技术 80
会议 80
自己 79
干部 78
职工 78
群众 77
没有 77
今天 76
同志 76
部门 75
加强 75
组织 75

点击下面链接下载中文词库素材(纯文本文件)
http://www.legalsoft.com.cn/download/cndict.rar

第一列是词,第二列是权重.我写的这个分词算法目前并未利用权重.

二、设计思路

算法简要描述:

对一个字符串S,从前到后扫描,对扫描的每个字,从词库中寻找最长匹配.比如假设S="我是中华人民共和国公民",词库中有"中华人民共和国","中华","公民","人民","共和国"......等词.当扫描到"中"字,那么从中字开始,向后分别取1,2,3,......个字("中","中华","中华人","中华人民","中华人民共","中华人民共和","中华人民共和国",,"中华人民共和国公"),词库中的最长匹配字符串是"中华人民共和国",那么就此切分开,扫描器推进到"公"字.
 
数据结构:

选择什么样的数据结构对性能影响很大.我采用Hashtable _rootTable记录词库.键值对为(键,插入次数).对每一个词语,如果该词语有N个字,则将该词语的1,1~2,1~3,......1~N个字作为键,插入_rootTable中.而同一个键如果重复插入,则后面的值递增.
 
三、程序

具体程序如下(程序中包含权重,插入次数等要素,目前的算法并没有利用这些.可以借此写出更有效的分词算法):

 


> 纯文本方式> 拷贝到裁剪板> 打印
01.public struct ChineseWordUnit 
02.{ 
03.    private string _word; 
04.    private int _power; 
05.    /// <summary> 
06.    /// 中文词语单元所对应的中文词。 
07.    /// </summary> 
08.    public string Word 
09.    { 
10.        get 
11.        { 
12.            return _word; 
13.        } 
14.    } 
15.    /// <summary> 
16.    /// 该中文词语的权重。 
17.    /// </summary> 
18.    public int Power 
19.    { 
20.        get 
21.        { 
22.            return _power; 
23.        } 
24.    } 
25.    /// <summary> 
26.    /// 结构初始化。 
27.    /// </summary> 
28.    /// <param name="word">中文词语</param> 
29.    /// <param name="power">该词语的权重</param> 
30.    public ChineseWordUnit(string word, int power) 
31.    { 
32.        this._word = word; 
33.        this._power = power; 
34.    } 
35.} 
36./// <summary> 
37./// 记录字符串出现在中文字典所录中文词语的前端的次数的字典类。如字符串"中"出现在"中国"的前端,则在字典中记录一个次数。 
38./// </summary> 
39.public class ChineseWordsHashCountSet 
40.{ 
41.    /// <summary> 
42.    /// 记录字符串在中文词语中出现次数的Hashtable。键为特定的字符串,值为该字符串在中文词语中出现的次数。 
43.    /// </summary> 
44.    private Hashtable _rootTable; 
45.    /// <summary> 
46.    /// 类型初始化。 
47.    /// </summary> 
48.    public ChineseWordsHashCountSet() 
49.    { 
50.        _rootTable = new Hashtable(); 
51.    } 
52.    /// <summary> 
53.    /// 查询指定字符串出现在中文字典所录中文词语的前端的次数。 
54.    /// </summary> 
55.    /// <param name="s">指定字符串</param> 
56.    /// <returns>字符串出现在中文字典所录中文词语的前端的次数。若为-1,表示不出现。</returns> 
57.    public int GetCount(string s) 
58.    { 
59.        if (!this._rootTable.ContainsKey(s.Length)) 
60.        { 
61.            return -1; 
62.        } 
63.        Hashtable _tempTable = (Hashtable)this._rootTable[s.Length]; 
64.        if (!_tempTable.ContainsKey(s)) 
65.        { 
66.            return -1; 
67.        } 
68.        return (int)_tempTable[s]; 
69.    } 
70.    /// <summary> 
71.    /// 向次数字典中插入一个词语。解析该词语,插入次数字典。 
72.    /// </summary> 
73.    /// <param name="s">所处理的字符串。</param> 
74.    public void InsertWord(string s) 
75.    { 
76.        for (int i = 0; i < s.Length; i++) 
77.        { 
78.            string _s = s.Substring(0, i + 1); 
79.            this.InsertSubString(_s); 
80.        } 
81.    } 
82.   /// <summary> 
83.    /// 向次数字典中插入一个字符串的次数记录。 
84.    /// </summary> 
85.    /// <param name="s">所插入的字符串。</param> 
86.    private void InsertSubString(string s) 
87.    { 
88.        if (!_rootTable.ContainsKey(s.Length) && s.Length > 0) 
89.        { 
90.            Hashtable _newHashtable = new Hashtable(); 
91.            _rootTable.Add(s.Length, _newHashtable); 
92.        } 
93.        Hashtable _tempTable = (Hashtable)_rootTable[s.Length]; 
94.        if (!_tempTable.ContainsKey(s)) 
95.        { 
96.            _tempTable.Add(s, 1); 
97.        } 
98.        else 
99.        { 
100.            _tempTable[s] = (int)_tempTable[s] + 1; 
101.        } 
102.    } 
103.} 
104./// <summary> 
105./// 中文分词器。 
106./// </summary> 
107.public class ChineseParse 
108.{ 
109.    private static ChineseWordsHashCountSet _countTable; 
110.    static ChineseParse() 
111.    { 
112.        _countTable = new ChineseWordsHashCountSet(); 
113.        InitFromFile("ChineseDictionary.txt"); 
114.    } 
115.    /// <summary> 
116.    /// 从指定的文件中初始化中文词语字典和字符串次数字典。 
117.    /// </summary> 
118.    /// <param name="fileName">文件名</param> 
119.    private static void InitFromFile(string fileName) 
120.    { 
121.        string path = Directory.GetCurrentDirectory() + @"\" + fileName; 
122.        if (File.Exists(path)) 
123.        { 
124.            using (StreamReader sr = File.OpenText(path)) 
125.            { 
126.                string s = ""; 
127.                while ((s = sr.ReadLine()) != null) 
128.                { 
129.                    ChineseWordUnit _tempUnit = InitUnit(s); 
130.                    _countTable.InsertWord(_tempUnit.Word); 
131.                } 
132.            } 
133.        } 
134.    } 
135.    /// <summary> 
136.    /// 将一个字符串解析为ChineseWordUnit。 
137.    /// </summary> 
138.    /// <param name="s">字符串</param> 
139.    /// <returns>解析得到的ChineseWordUnit<40         
140.    private static ChineseWordUnit InitUnit(string s) 
141.    { 
142.        Regex reg = new Regex(@"\s+"); 
143.        string[] temp = reg.Split(s); 
144.        if (temp.Length != 2) 
145.        { 
146.            throw new Exception("字符串解析错误:" + s); 
147.        } 
148.        return new ChineseWordUnit(temp[0], Int32.Parse(temp[1])); 
149.    } 
150.    /// <summary> 
151.    /// 分析输入的字符串,将其切割成一个个的词语。 
152.    /// </summary> 
153.    /// <param name="s">待切割的字符串</param> 
154.    /// <returns>所切割得到的中文词语数组</returns> 
155.    public static string[] ParseChinese(string s) 
156.    { 
157.        int _length = s.Length; 
158.        string _temp = String.Empty; 
159.        ArrayList _words = new ArrayList(); 
160.        for (int i = 0; i < s.Length; ) 
161.        { 
162.            _temp = s.Substring(i, 1); 
163.            if (_countTable.GetCount(_temp) > 1) 
164.            { 
165.                int j = 2; 
166.                for (; i + j < s.Length + 1 && _countTable.GetCount(s.Substring(i, j)) > 0; j++) 
167.                { 
168.                } 
169.                _temp = s.Substring(i, j - 1); 
170.                i = i + j - 2; 
171.            } 
172.            i++; 
173.            _words.Add(_temp); 
174.        } 
175.        string[] _tempStringArray = new string[_words.Count]; 
176.        _words.CopyTo(_tempStringArray); 
177.        return _tempStringArray; 
178.    } 
179.} 

 进一步应该做的:
1,能识别简单的外语,数字
2,具备简单智能
3,扩充词库

然后就有实用价值了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值