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


    一、词库 

    词库大概有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,扩充词库 

    然后就有实用价值了. 
  • 相关阅读:
    React-Native 基本环境的搭建
    initWithFrame 与 initWithCoder 、awakeFromNib 的方法理解笔记
    关于 jwTextFiled 的使用说明
    使用 SourceTree 遇到冲突的解决方法
    如何使用最简单的方法将一个已经存在的工程中使用 cocaPodfile
    使用 NSData 分类实现,对 NSData 数据类型进行 AES 加密
    相机检测
    纯代码适配优化方案之一(内联函数的使用)
    页面跳转问题,多次 push 到新的页面的问题的解决方法
    判断银行卡卡号输入的合法性接口
  • 原文地址:https://www.cnblogs.com/top5/p/1976925.html
Copyright © 2020-2023  润新知