简单实用的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中.而同一个键如果重复插入,则后面的值递增.

三、程序

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

  1. public struct ChineseWordUnit   
  2. {   
  3.     private string _word;   
  4.     private int _power;   
  5.     /// <summary>   
  6.     /// 中文词语单元所对应的中文词。   
  7.     /// </summary>   
  8.     public string Word   
  9.     {   
  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、付费专栏及课程。

余额充值