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

ChineseWordUnit.cs //struct--(词语,权重)对

1 public struct ChineseWordUnit
2 {
3 private string _word;
4 private int _power;
5
6 /** <summary>
7 /// 中文词语单元所对应的中文词。
8 /// </summary>
9 public string Word
10 {
11 get
12 {
13 return _word;
14 }
15 }
16
17 /** <summary>
18 /// 该中文词语的权重。
19 /// </summary>
20 public int Power
21 {
22 get
23 {
24 return _power;
25 }
26 }
27
28 /** <summary>
29 /// 结构初始化。
30 /// </summary>
31 /// <param name="word">中文词语</param>
32 /// <param name="power">该词语的权重</param>
33 public ChineseWordUnit(string word, int power)
34 {
35 this._word = word;
36 this._power = power;
37 }
38 }

ChineseWordsHashCountSet.cs //词库容器

1 /** <summary>
2 /// 记录字符串出现在中文字典所录中文词语的前端的次数的字典类。如字符串“中”出现在“中国”的前端,则在字典中记录一个次数。
3 /// </summary>
4 public class ChineseWordsHashCountSet
5 {
6 <summary>
7 /// 记录字符串在中文词语中出现次数的Hashtable。键为特定的字符串,值为该字符串在中文词语中出现的次数。
8 /// </summary>
9 private Hashtable _rootTable;
10
11 <summary>
12 /// 类型初始化。
13 /// </summary>
14 public ChineseWordsHashCountSet()
15 {
16 _rootTable = new Hashtable();
17 }
18
19 <summary>
20 /// 查询指定字符串出现在中文字典所录中文词语的前端的次数。
21 /// </summary>
22 /// <param name="s">指定字符串</param>
23 /// <returns>字符串出现在中文字典所录中文词语的前端的次数。若为-1,表示不出现。</returns>
24 public int GetCount(string s)
25 {
26 if (!this._rootTable.ContainsKey(s.Length))
27 {
28 return -1;
29 }
30 Hashtable _tempTable = (Hashtable)this._rootTable[s.Length];
31 if (!_tempTable.ContainsKey(s))
32 {
33 return -1;
34 }
35 return (int)_tempTable[s];
36 }
37
38 <summary>
39 /// 向次数字典中插入一个词语。解析该词语,插入次数字典。
40 /// </summary>
41 /// <param name="s">所处理的字符串。</param>
42 public void InsertWord(string s)
43 {
44 for(int i=0;i<s.Length;i++)
45 {
46 string _s = s.Substring(0,i+1);
47 this.InsertSubString(_s);
48 }
49 }
50
51 <summary>
52 /// 向次数字典中插入一个字符串的次数记录。
53 /// </summary>
54 /// <param name="s">所插入的字符串。</param>
55 private void InsertSubString(string s)
56 {
57 if (!_rootTable.ContainsKey(s.Length)&&s.Length>0)
58 {
59 Hashtable _newHashtable = new Hashtable();
60 _rootTable.Add(s.Length,_newHashtable);
61 }
62 Hashtable _tempTable = (Hashtable)_rootTable[s.Length];
63 if (!_tempTable.ContainsKey(s))
64 {
65 _tempTable.Add(s,1);
66 }
67 else
68 {
69 _tempTable[s]=(int)_tempTable[s]+1;
70 }
71 }
72 }

ChineseParse.cs //分词器

1 <summary>
2 /// 中文分词器。
3 /// </summary>
4 public class ChineseParse
5 {
6 private static ChineseWordsHashCountSet _countTable;
7
8 static ChineseParse()
9 {
10 _countTable = new ChineseWordsHashCountSet();
11 InitFromFile("ChineseDictionary.txt");
12 }
13
14 <summary>
15 /// 从指定的文件中初始化中文词语字典和字符串次数字典。
16 /// </summary>
17 /// <param name="fileName">文件名</param>
18 private static void InitFromFile(string fileName)
19 {
20 string path = Directory.GetCurrentDirectory() +@"\" + fileName;
21 if (File.Exists(path))
22 {
23 using (StreamReader sr = File.OpenText(path))
24 {
25 string s = "";
26 while ((s = sr.ReadLine()) != null)
27 {
28 ChineseWordUnit _tempUnit = InitUnit(s);
29 _countTable.InsertWord(_tempUnit.Word);
30 }
31 }
32 }
33 }
34
35 /** <summary>
36 /// 将一个字符串解析为ChineseWordUnit。
37 /// </summary>
38 /// <param name="s">字符串</param>
39 /// <returns>解析得到的ChineseWordUnit</returns>
40 private static ChineseWordUnit InitUnit(string s)
41 {
42 Regex reg = new Regex(@"\s+");
43 string[] temp = reg.Split(s);
44 if (temp.Length!=2)
45 {
46 throw new Exception("字符串解析错误:"+s);
47 }
48 return new ChineseWordUnit(temp[0],Int32.Parse(temp[1]));
49 }
50
51 /** <summary>
52 /// 分析输入的字符串,将其切割成一个个的词语。
53 /// </summary>
54 /// <param name="s">待切割的字符串</param>
55 /// <returns>所切割得到的中文词语数组</returns>
56 public static string[] ParseChinese(string s)
57 {
58 int _length = s.Length;
59 string _temp = String.Empty;
60 ArrayList _words = new ArrayList();
61
62 for(int i=0;i<s.Length;)
63 {
64 _temp = s.Substring(i,1);
65 if (_countTable.GetCount(_temp)>1)
66 {
67 int j=2;
68
69 for (;i+j<s.Length+1&&_countTable.GetCount(s.Substring(i,j))>0;j++)
70 {
71 }
72 _temp = s.Substring(i,j-1);
73 i = i + j - 2;
74 }
75 i++;
76 _words.Add(_temp);
77 }
78
79 string[] _tempStringArray = new string[_words.Count];
80 _words.CopyTo(_tempStringArray);
81 return _tempStringArray;
82 }
83 }

四、测试

和海量分词演示程序对比测试:

Case 1:  新浪体育讯 在被尤文淘汰之后,皇马主帅博斯克拒绝接受媒体对球队后防线的批评,同时还为自己排出的首发阵容进行了辩护。“失利是全队的责任,而不仅仅是后防线该受指责,”博斯克说,“我并不认为我们踢得一塌糊涂。”“我们进入了半决赛,而且在晋级的道路上一路奋战。即使是今天的比赛我们也有几个翻身的机会,但我们面对的对手非常强大,他们踢得非常好。”“我们的球迷应该为过去几个赛季里我们在冠军杯中的表现感到骄傲。”博斯克还说。对于博斯克在首发中排出了久疏战阵的坎比亚索,赛后有记者提出了质疑,认为完全应该将队内的另一名球员帕文派遣上场以加强后卫线。对于这一疑议,博斯克拒绝承担所谓的“责任”,认为球队的首发没有问题。“我们按照整个赛季以来的方式做了,对于人员上的变化我没有什么可说的。”对于球队在本赛季的前景,博斯克表示皇马还有西甲联赛的冠军作为目标。“皇家马德里在冠军杯中战斗到了最后,我们在联赛中也将这么做。”

海量分词结果:

    新浪 体育 讯   在 被 尤文 淘汰 之后 , 皇马 主帅 博斯克 拒绝 接受 媒体 对 球队 后防线 的 批评 , 同时 还 为 自己 排出 的 首发 阵容 进行 了 辩护 。 “ 失利 是 全队 的 责任 , 而 不 仅仅 是 后防线 该 受 指责 , ” 博斯克 说 , “ 我 并 不 认为 我们 踢 得 一塌糊涂 。” “ 我们 进入 了 半决赛 , 而且 在 晋级 的 道路 上 一路 奋战 。 即使 是 今天 的 比赛 我们 也 有 几个 翻身 的 机会 , 但 我们 面对 的 对手 非常 强大 , 他们 踢 得 非常 好 。” “ 我们 的 球迷 应该 为 过去 几个 赛季 里 我们 在 冠军 杯中 的 表现 感到 骄傲 。” 博斯克 还 说 。 对于 博斯克 在 首发 中 排出 了 久 疏 战阵 的 坎比亚索 , 赛后 有 记者 提出 了 质疑 , 认为 完全 应该 将 队 内 的 另 一名 球员 帕文 派遣 上场 以 加强 后卫线 。 对于 这 一 疑 议 , 博斯克 拒绝 承担 所谓 的 “ 责任 ” , 认为 球队 的 首发 没有 问题 。 “ 我们 按照 整个 赛季 以来 的 方式 做 了 , 对于 人员 上 的 变化 我 没有 什么 可 说 的 。” 对于 球队 在 本 赛季 的 前景 , 博斯克 表示 皇马 还有 西 甲 联赛 的 冠军 作为 目标 。 “ 皇家 马德里 在 冠军 杯中 战斗 到 了 最后 , 我们 在 联赛 中 也 将 这么 做 。”

ChineseParse分词结果:

    新 浪 体育 讯   在 被 尤 文 淘汰 之后 , 皇 马 主帅 博斯 克 拒绝 接受 媒体 对 球队 后防线 的 批评 , 同时 还 为 自己 排 出 的 首发 阵容 进行 了 辩护 。“ 失利 是 全队 的 责任 , 而 不仅仅 是 后防线 该 受 指责 , ” 博斯 克 说 , “ 我 并 不 认为 我们 踢 得 一塌糊涂 。 ” “ 我们 进入 了 半决赛 , 而且 在 晋级 的 道路 上一 路 奋战 。 即使 是 今天 的 比赛 我们 也 有 几 个 翻身 的 机会 , 但 我们 面对 的 对手 非常 强大 , 他们 踢 得 非常 好 。 ” “ 我们 的 球迷 应该 为 过 去 几 个 赛季 里 我们 在 冠军杯 中 的 表现 感到 骄傲 。 ” 博斯 克 还 说 。对于 博斯 克 在 首发 中排 出 了 久 疏 战 阵 的 坎 比 亚 索 , 赛后 有 记者 提出 了 质疑 , 认为 完全 应该 将 队 内 的 另一 名 球员 帕 文 派遣 上场 以 加强 后卫线 。 对于 这一 疑 议 , 博斯 克 拒绝 承担 所谓 的 “ 责任 ” , 认为 球队 的 首发 没有 问题 。 “ 我们 按照 整个 赛季 以来 的 方式 做 了 , 对于 人员 上 的 变化 我 没有 什么 可 说 的 。 ” 对于 球队 在 本赛 季 的 前景 , 博斯 克 表示 皇 马 还有 西 甲 联赛 的 冠军 作为 目标 。 “ 皇家 马德里 在 冠军杯 中 战斗 到 了 最后 , 我们 在 联赛 中 也 将 这么 做 。 ”

因为没有体育专业词库和人名专业词库,所以ChineseParse不能认识这些专业词.

Case 2: 我国汽车社会第一次重大转型历经十多年时间。在1994年出台的《汽车工业产业政策》中,最醒目的一条就是“逐步改变以行政机关、团体、事业单位及国有企业为主的公款购买、使用小汽车的消费结构”。从公款购买汽车为主到汽车逐渐进入家庭,第一次重大转型给人民生活质量带来了巨大提升。这次转型的主要推动力是态度鲜明的产业政策、持续高速增长的国民经济以及蓬勃发展的国内汽车工业。 然而,当我们快速迈进以私人汽车为主体的汽车社会的时候,也面临着新的形势、新的考验:中央强调树立和落实科学发展观,要求国内企业提高自主创新能力;今年“两会”期间,中央又提出构建和谐社会和节约型社会的精神;同时,我国汽车社会面临能源紧缺、燃油价格上涨、土地资源有限等诸多不利因素。在这样的大背景下,进行第二次重大转型刻不容缓。

海量分词结果:

我国 汽车 社会 第一次 重大 转型 历经 十多年 时间 。 在 1994年 出台 的 《 汽车 工业 产业 政策 》 中 , 最 醒目 的 一条 就是 “ 逐步 改变 以 行政 机关 、 团体 、 事业 单位 及 国有 企业 为主 的 公款 购买 、 使用 小汽车 的 消费 结构 ” 。 从 公款 购买 汽车 为主 到 汽车 逐渐 进入 家庭 , 第一次 重大 转型 给 人民 生活 质量 带来 了 巨大 提升 。 这次 转型 的 主要 推动力 是 态度 鲜明 的 产业 政策 、 持续 高速 增长 的 国民经济 以及 蓬勃 发展 的 国内 汽车 工业 。 然而 , 当 我们 快速 迈进 以 私人 汽车 为 主体 的 汽车 社会 的 时候 , 也 面临 着 新 的 形势 、 新 的 考验 : 中央 强调 树立 和 落实 科学 发展观 , 要求 国内 企业 提高 自主 创新 能力 ; 今年 “ 两会 ” 期间 , 中央 又 提出 构建 和谐 社会 和 节约型 社会 的 精神 ; 同时 , 我国 汽车 社会 面临 能源 紧缺 、 燃油 价格 上涨 、 土地 资源 有限 等 诸多 不利 因素 。 在 这样 的 大 背景 下 , 进行 第二次 重大 转型 刻不容缓 。

ChineseParse分词结果:

我国 汽车 社会 第一 次 重大 转型 历经 十 多年 时间 。 在 1 9 9 4 年 出台 的 《 汽车 工业 产业 政策 》 中 , 最 醒目 的 一条 就是 “ 逐步 改变 以 行政 机关 、团体 、 事业 单位 及 国有 企业 为主 的 公款 购买 、 使用 小汽车 的 消费 结构 ”。 从 公款 购买 汽车 为主 到 汽车 逐渐 进入 家庭 , 第一 次 重大 转型 给 人民 生活 质量 带来 了 巨大 提升 。 这次 转型 的 主要 推动力 是 态度 鲜明 的 产业 政策 、 持续 高速 增长 的 国民经济 以及 蓬勃 发展 的 国内 汽车 工业 。 然而 , 当 我们 快速 迈进 以 私人 汽车 为主 体 的 汽车 社会 的 时候 , 也 面临 着 新 的 形势 、 新 的 考验 : 中央 强调 树立 和 落实 科学 发展观 , 要求 国内 企业 提高 自主 创新 能力 ; 今年 “ 两会 ” 期间 , 中央 又 提出 构建 和谐 社会 和 节约 型 社会 的 精神 ; 同时 , 我国 汽车 社会 面临 能源 紧缺 、 燃油 价格 上涨 、 土地 资源 有限 等 诸多不 利 因素 。 在 这样 的 大 背景 下 , 进行 第二 次 重大 转型 刻不容缓 。

可以看出,ChineseParse不能智能处理"第一次","第二次"这种词,对数字也没识别能力,不过基本的分词效果还是可以的.

(毕竟我3个小时就把程序搞定了,怎么能和别人十年积累的比呢?)

性能测试(迅驰1.5M): 每秒钟67.7万字

程序优化有应该更高.

五、小结

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

然后就有实用价值了.

注:前几个月写的大多都是诸如此类简单的中文处理小程序,如繁简转换,自动排版,批量替换,中文分词,有时间的话我会把这些程序集中起来打包成一个实用的中文处理工具.不知道大家还有什么需求,不防说说.

基于逆向最大化词表中文分词法。
以前做知识管理系统的时候,由于需要建立全文检索和统计词频,需要对中文文本进行分词。对于中文分词,

国内做到好的应该是中科院自然研究所,但是相对比较复杂,我看了几次没有看明白. :) ,由于平常我们的知识系统

对分词的要求没有这么高,所以 就选择了最大化的词表分词法. 词表选择的是人民日报97版的词表.

实际效果可以达到90%以上,基本可以满足需要。支持 Lucene.net分词,词表是启动时一次性载入;

具体代码如下:

public sealed class LtWordTokenizer : Tokenizer
{
private String bufferText;
private ArrayList wordArray;
private int intIndex=0;
public static Hashtable hsDic=new Hashtable();

public LtWordTokenizer(TextReader _in)
{
input = _in;
bufferText=input.ReadToEnd().ToLower();
wordArray=new ArrayList();
wordSegment(bufferText);

}

public void wordSegment(String Sentence)
{
int senLen = Sentence.Length;
int i=0, j=0;
int M=12;
string word;
while(i < senLen)
{
int N= i+M<senLen ? i+M : senLen+1;
bool bFind=false;
for(j=N-1; j>i; j--)
{
word = Sentence.Substring(i, j-i).Trim();
if(hsDic.ContainsKey(word.Trim()))
{
wordArray.Add(new Token(word,i,i+word.Length));
bFind=true;
i=j;
break;
}
}
if(!bFind)
{
word = Sentence.Substring(i, 1).Trim();
i=j+1;
if(word.Trim()!="")
{
wordArray.Add(new Token(word,i,i+word.Length));
}
}
}
}

public override Token Next()
{

if(intIndex<wordArray.Count)
{
intIndex++;
return (Token)(wordArray[intIndex-1]);
}
else
return null;
}

}
}

下次可以在分词的时候更改一下,不必先分好保存到arraylist,动态速度更好

中文分词-转载3_一个北京程序员相关推荐

  1. 转载:一个平庸程序员的自白(豆瓣深度好文)

    题记: 前一篇随笔:做一个平庸程序员,are you scared?博文中提到的豆瓣深度好文原文,想想还是转载过来吧,以免作者将原文给删掉.怎奈CSDN转载不是很方便,这里就直接截屏了,有兴趣的大家可 ...

  2. 转载的在北京程序员如何做到月入2万???

    首先两万的月薪在BAT实在太普遍了,一般是高级工程师和资深工程师的职位.在阿里是p6左右,在百度是t5左右,腾讯是t2-3左右,京东是t3-1,美团是p6左右,其他的我不了解.这种级别是他们主要码农层 ...

  3. 【转载】一个硕士程序员的求婚日记——做开发的不是木头人!

    纪念3月6日:求婚时单腿下跪 我的膝盖青了一块! 七年,  或许小学毕业,步入初中:  或许从本科到硕士,步入社会:  或许从小工到专家,步入事业高峰:  或许,或许,还有更多!  我们在一起,其实已 ...

  4. 转载 一个游戏程序员的学习资料

    转载]一个游戏程序员的学习资料 2008-05-15 20:31 日志原文:http://xoyojank.blog.sohu.com/83788512.html 想起写这篇文章是在看侯杰先生的< ...

  5. 一个老程序员的心里话(转载)

    1.希特勒地堡与cih病毒 99年4月,我来到北京参加研究生复试.复试完了之后就不回去了,我拿着一张光盘,里面刻着我用vb和authorware3.5编的一个cool 3d的教学软件,到处参加招聘会, ...

  6. 一个月薪12000的北京程序员的真实生活

    本文作者:白公子 " 每个人都有自己的亲身经历,每个人都有一条生活道路.千万人,千万条,各不相同,各有特点.但是并不是好人都有一条好路,坏人都有一坏路.有的时候却恰恰相反.这虽然不是历史的必 ...

  7. 讲述:一个月薪12000的北京程序员的真实生活

    " 每个人都有自己的亲身经历,每个人都有一条生活道路.千万人,千万条,各不相同,各有特点.但是并不是好人都有一条好路,坏人都有一坏路.有的时候却恰恰相反.这虽然不是历史的必然,但却是客观社会 ...

  8. 一个月薪3W,但有点失败的北京程序员的真实生活!!!

    月薪30K的北漂一族都过着什么样的生活? 在很多人眼里,月薪30K的生活至少是这样的:左手手握一杯星巴克,右手持握plus手机,出入写字楼,杰克大卫叫着,徒手撸系统,单针戳光盘,一星期7件格子衫不重样 ...

  9. 一个JAVA程序员成长之路(转载)

    我搞JAVA也有些日子了, 因为我比较贪玩,上进心不那么强, 总是逼不得已为了高薪跳槽才去学习, 所以也没混成什么大牛, 但好在现在也已经成家立业, 小日子过的还算滋润, 起码顶得住一月近万元的吃喝拉 ...

最新文章

  1. UVa11300 - Spreading the Wealth
  2. c if 判断select已经选择的值_Golang语言基础教程:if分支语句
  3. apache-shiro杂记(三) 用了apache-shiro后,HttpSession.getServletContext() API无法正常工作了...
  4. iOS10 UI教程视图的中心位置
  5. 成员缩写_「gnps,nbcs」是什么意思?00后饭圈缩写你看懂多少
  6. 手把手教你安装VMware虚拟机
  7. linux系统ftp优化,Linux vsftp 部署优化
  8. printf() 输出控制符
  9. Elasticsearch6.3.0安装Ansj分词插件
  10. 本地 hosts 文件找不到怎么办
  11. Quartz-第一篇 认识Quartz
  12. Linux下编译安装redis,详细教程
  13. optistruct线性求解一次二次单元应力位移比较
  14. Pytorch-早停法(early stopping)原理及其代码
  15. Linux的LILO引导程序,LILO引导装载器详解
  16. 39.JavaScript中Promise的基本概念、使用方法,回调地狱规避、链式编程
  17. axios的并发请求和 排队请求
  18. Linux下编译pjproject-2.6并运行例程simple_pjsua
  19. QT案例实战1 - 从零开始编写一个OCR工具软件 (7) 屏幕截图/图像展示/文字识别
  20. vim 复制、删除多行

热门文章

  1. 转载自科技猿人:联想5G投票这事,我们就来彻底讲清楚
  2. Stata——固定效应模型、随机效应模型、混合效应模型(区别、实例)
  3. 高德地图:点击获取火星坐标(经纬度)
  4. R绘图 第八篇:绘制饼图(ggplot2)
  5. android 手机存储大小设置,安卓手机怎么设置增加虚拟内存
  6. PostgreSQL 179个场景
  7. Python简笔画——用Turtle库画一只《穿红靴子的小鸭》
  8. 企业为什么要选择人力外包?好处与坏处
  9. 江在川上曰:less样式预编译
  10. 如何用echarts实现颜色渐变半圆形仪表盘