TrieTree介绍及其C#实现
作者:Tony Qu
在自然语言处理(NLP)研究中,NGram是最基本但也是最有用的一种比对方式,这里的N是需要比对的字符串的长度,而今天我介绍的TrieTree,正是和NGram密切相关的一种数据结构,有人称之为字典树。TrieTree简单的说是一种多叉树,每个节点保存一个字符,这么做的好处是当我们要做NGram比对时,只需要直接从树的根节点开始沿着某个树叉遍历下去,就能完成比对;如果没找到,停止本次遍历。这话讲得有些抽象,我们来看一个实际的例子。
假设我们现在词库里面有以下一些词:
上海市
上海滩
上海人
上海公司
北京
北斗星
杨柳
杨浦区
如图所示:挂在根节点上的字有上、北、杨,
如果我们现在对“上海市杨浦区”这个词做3gram就有上海市、海市杨、市杨浦、杨浦区,现在我们要知道哪些词是能够被这个字典识别的,通常我们可以用NGram来做分词。有了这颗树,我们只需要依次取每个字符,从根开始进行比对,比如上海市,我们能够匹配 上->海->市,这个路径,所以匹配;比如海市杨,由于没有“海”字挂在根节点上,所以停止;市杨浦也无法匹配;最终匹配杨浦区,得到 杨->浦->区 这个路径,匹配。
最终我们可以把“上海市杨浦区”切分为 上海市|杨浦区。
尽管TrieTree要比普通字符串数组节省很多时间,但这并不是没有代价的,因为你要先根据字典构建这棵树,这个代价并不低,当然对于某个应用来说一旦TrieTree构建完成就可以重复使用,所以针对大规模比对来说,性能提升还是很客观的。
下面是TrieTree的C#实现。
public class TrieTree { TrieNode _root = null; private TrieTree() { _root = new TrieNode(char.MaxValue,0); charCount = 0; } static TrieTree _instance = null; public static TrieTree GetInstance() { if (_instance == null) { _instance = new TrieTree(); } return _instance; } public TrieNode Root { get { return _root; } } public void AddWord(char ch) { TrieNode newnode=_root.AddChild(ch); newnode.IncreaseFrequency(); newnode.WordEnded = true; } int charCount; public void AddWord(string word) { if (word.Length == 1) { AddWord(word[0]); charCount++; } else { char[] chars=word.ToCharArray(); TrieNode node = _root; charCount += chars.Length; for (int i = 0; i < chars.Length; i++) { TrieNode newnode=node.AddChild(chars[i]); newnode.IncreaseFrequency(); node = newnode; } node.WordEnded = true; } } public int GetFrequency(char ch) { TrieNode matchedNode = _root.Children.FirstOrDefault(n => n.Character == ch); if (matchedNode == null) { return 0; } return matchedNode.Frequency; } public int GetFrequency(string word) { if (word.Length == 1) { return GetFrequency(word[0]); } else { char[] chars = word.ToCharArray(); TrieNode node = _root; for (int i = 0; i < chars.Length; i++) { if (node.Children == null) return 0; TrieNode matchednode = node.Children.FirstOrDefault(n => n.Character == chars[i]); if (matchednode == null) { return 0; } node = matchednode; } if (node.WordEnded == true) return node.Frequency; else return -1; } } }
这里我们使用了单例模式,因为TrieTree类似缓存,不需要重复创建。下面是TreeNode的实现:
public class TrieNode { public TrieNode(char ch,int depth) { this.Character=ch; this._depth=depth; } public char Character; int _depth; public int Depth { get{return _depth;} } TrieNode _parent=null; public TrieNode Parent { get { return _parent; } set { _parent = value; } } public bool WordEnded = false; HashSet<TrieNode> _children=null; public HashSet<TrieNode> Children { get { return _children; } } public TrieNode GetChildNode(char ch) { if (_children != null) return _children.FirstOrDefault(n => n.Character == ch); else return null; } public TrieNode AddChild(char ch) { TrieNode matchedNode=null; if (_children != null) { matchedNode = _children.FirstOrDefault(n => n.Character == ch); } if (matchedNode != null) //found the char in the list { //matchedNode.IncreaseFrequency(); return matchedNode; } else { //not found TrieNode node = new TrieNode(ch, this.Depth + 1); node.Parent = this; //node.IncreaseFrequency(); if (_children == null) _children = new HashSet<TrieNode>(); _children.Add(node); return node; } } int _frequency = 0; public int Frequency { get { return _frequency; } } public void IncreaseFrequency() { _frequency++; } public string GetWord() { TrieNode tmp=this; string result = string.Empty; while(tmp.Parent!=null) //until root node { result = tmp.Character + result; tmp = tmp.Parent; } return result; } public override string ToString() { return Convert.ToString(this.Character); } }
最后提供一个能工作的演示代码,供大家参考,点击 这里 下载。
TrieTree介绍及其C#实现
摘要: 本文给大家介绍TrieTree数据结构,这是NGram研究中必备的结构体之一。 阅读全文
posted @ 2012-02-11 14:40 Tony Qu 阅读(654) | 评论 (0) 编辑
.net 2.0下的OOXML神器:NPOI.OpenXml4Net
posted @ 2012-01-12 06:34 Tony Qu 阅读(1841) | 评论 (9) 编辑
WCSF vs ASP.NET MVC
摘要: 相对于ASP.NET MVC,WCSF显得默默无闻许多,可能大部分人没有听到过这个框架,但是它确实存在,而且是pattern&practice team的大作。 阅读全文
posted @ 2010-09-15 23:23 Tony Qu 阅读(2632) | 评论 (10) 编辑
Java转C#实践(一):数值类型的使用
posted @ 2010-05-25 03:35 Tony Qu 阅读(992) | 评论 (0) 编辑
NPOI实践: .NET导入Excel文件的另一种选择
posted @ 2009-12-25 16:50 Tony Qu 阅读(14686) | 评论 (31) 编辑
NPOI 1.2教程 - 2.2.1 设置单元格格式
摘要: NPOI 1.2教程的2.2.1节,2.2节开始将详细讲解单元格的一些相关功能和代码实现。 阅读全文
posted @ 2009-03-27 09:01 Tony Qu 阅读(12516) | 评论 (11) 编辑
NPOI 1.2教程 - 2.1.3 创建单元格
posted @ 2009-03-25 09:58 Tony Qu 阅读(7781) | 评论 (5) 编辑
NPOI 1.2教程 - 2.1.2 创建DocumentSummaryInformation和SummaryInformation
摘要: 这是NPOI 1.2教程第2章的1.2节,通过这一节你将了解什么是DocumentSummaryInformation和SummaryInformation,以及如何在NPOI中创建它们。 阅读全文
posted @ 2009-03-24 07:11 Tony Qu 阅读(7137) | 评论 (6) 编辑
NPOI 1.2教程 - 2.1.1 创建Workbook和Sheet
摘要: 这文是NPOI 1.2教程第2章的第一节,从创建Workbook开始一步步教你如何使用NPOI 1.2创建“纯种”Excel 97-2003的xls文件 阅读全文
posted @ 2009-03-23 07:41 Tony Qu 阅读(15995) | 评论 (15) 编辑
NPOI简介
摘要: NPOI开源项目的介绍,如果你正为生成Excel文件格式而烦恼,这套库会让你多一个选择。 阅读全文
posted @ 2009-03-16 07:49 Tony Qu 阅读(19281) | 评论 (45) 编辑
如何隐藏UpdatePanel
posted @ 2008-04-22 10:08 Tony Qu 阅读(1421) | 评论 (2) 编辑
[翻译].NET牛人应该知道些什么
posted @ 2008-02-22 15:05 Tony Qu 阅读(2348) | 评论 (8) 编辑
老调重弹——你存储的密码做Hash了吗?
posted @ 2007-12-18 18:06 Tony Qu 阅读(3903) | 评论 (27) 编辑
如何检测是否安装了.NET 2.0和.NET 3.0
posted @ 2007-10-07 17:22 Tony Qu 阅读(1647) | 评论 (6) 编辑
ActiveSync错误号85010014故障排除实践
摘要: 前两天尝试用ActiveSync同步联系人,没想到刚安装好ActiveSync就出问题,于是只能自己帮自己做troubleshooting,当然是有收获的,所以写篇文章和大家分享一下 阅读全文
posted @ 2007-04-17 02:09 Tony Qu 阅读(41161) | 评论 (77) 编辑
VS2005 SP1中一个改进(很容易被认为是bug)
posted @ 2007-03-17 07:02 Tony Qu 阅读(4420) | 评论 (21) 编辑
基于Visual Studio 2003/2005的Office插件开发FAQ
posted @ 2007-02-05 23:19 Tony Qu 阅读(6464) | 评论 (17) 编辑
如何在运行时改变User Profile的Provider
摘要: 在网上找遍了也没有找到 运行时改变User Profile的Provider的方法,于是研究了一下,总的来说还是比较简单的,但有些技巧性 阅读全文
posted @ 2006-12-26 17:12 Tony Qu 阅读(2488) | 评论 (5) 编辑
理解Session State模式+ASP.NET SESSION丢失FAQ [翻译]
摘要: 微软asp.net论坛上最经典的session lost troubleshooting帖子。由于发觉这份文档一直没有人翻译,故翻译之,相信可以帮助很多朋友解决session lost的困惑。 阅读全文
posted @ 2006-10-24 22:10 Tony Qu 阅读(21677) | 评论 (12) 编辑
关于VS2005中的Code Snippets Manager的问题及解决
posted @ 2006-06-29 18:23 Tony Qu 阅读(3194) | 评论 (6) 编辑
aspnetdb.mdf数据字典
posted @ 2006-05-19 15:28 Tony Qu 阅读(5061) | 评论 (7) 编辑
使用ASP.NET 2.0 Profile存储用户信息[翻译] Level 200
摘要: User Profile作为asp.net 2.0的新特性之一,有相当的实用价值,本文是有关user profile的配置及使用教材,有任何翻译上或内容方面的问题请指出。
由于文章较长,用了一个星期才翻译完,在此庆祝一下:D。 阅读全文
posted @ 2005-12-18 08:19 Tony Qu 阅读(15282) | 评论 (27) 编辑
ASP.NET 2.0基于SQLSERVER 2005的aspnetdb.mdf部署
posted @ 2005-12-02 01:26 Tony Qu 阅读(15543) | 评论 (26) 编辑
VS2005 ASP.NET本地化学习笔记&感受
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于TrieTree介绍及其C#实现的详细内容...