trie树的定义这里就不多说了,直接贴代码(代码大部分是参考别人的,修改了个别错误,并添加了一个最大匹配的方法)。

package com.fox.analyzer;import java.util.ArrayList;
import java.util.List;public class Trie {private Vertex root = new Vertex();protected class Vertex {protected int words; // 单词个数protected int prefixes; // 前缀个数protected Vertex[] edges; // 子节点Vertex() {this.words = 0;this.prefixes = 0;edges = new Vertex[26];for (int i = 0; i < edges.length; i++) {edges[i] = null;}}}/*** 获取tire树中所有的词* * @return*/public List<String> listAllWords() {List<String> words = new ArrayList<String>();Vertex[] edges = root.edges;for (int i = 0; i < edges.length; i++) {if (edges[i] != null) {String word = "" + (char) ('a' + i);depthFirstSearchWords(words, edges[i], word);}}return words;}/*** * @param words* @param vertex* @param wordSegment*/private void depthFirstSearchWords(List words, Vertex vertex,String wordSegment) {if (vertex.words != 0) {words.add(wordSegment);}Vertex[] edges = vertex.edges;for (int i = 0; i < edges.length; i++) {if (edges[i] != null) {String newWord = wordSegment + (char) ('a' + i);depthFirstSearchWords(words, edges[i], newWord);}}}/*** 计算指定前缀单词的个数* * @param prefix* @return*/public int countPrefixes(String prefix) {return countPrefixes(root, prefix);}private int countPrefixes(Vertex vertex, String prefixSegment) {if (prefixSegment.length() == 0) { // reach the last character of the// wordreturn vertex.prefixes;}char c = prefixSegment.charAt(0);int index = c - 'a';if (vertex.edges[index] == null) { // the word does NOT existreturn 0;} else {return countPrefixes(vertex.edges[index],prefixSegment.substring(1));}}/*** 计算完全匹配单词的个数* * @param word* @return*/public int countWords(String word) {return countWords(root, word);}private int countWords(Vertex vertex, String wordSegment) {if (wordSegment.length() == 0) { // reach the last character of the wordreturn vertex.words;}char c = wordSegment.charAt(0);int index = c - 'a';if (vertex.edges[index] == null) { // the word does NOT existreturn 0;} else {return countWords(vertex.edges[index], wordSegment.substring(1));}}/*** 向tire树添加一个词* * @param word* */public void addWord(String word) {addWord(root, word);}/*** Add the word from the specified vertex.* * @param vertex*            The specified vertex.* @param word*            The word to be added.*/private void addWord(Vertex vertex, String word) {if (word.length() == 0) { // if all characters of the word has been// addedvertex.words++;} else {vertex.prefixes++;char c = word.charAt(0);c = Character.toLowerCase(c);int index = c - 'a';if (vertex.edges[index] == null) { // if the edge does NOT existvertex.edges[index] = new Vertex();}addWord(vertex.edges[index], word.substring(1)); // go the the next// character}}/*** 返回指定字段前缀匹配最长的单词。* * @param word* @return*/public String getMaxMatchWord(String word) {String s = "";String temp = "";// 记录最近一次匹配最长的单词char[] w = word.toCharArray();Vertex vertex = root;for (int i = 0; i < w.length; i++) {char c = w[i];c = Character.toLowerCase(c);int index = c - 'a';if (vertex.edges[index] == null) {// 如果没有子节点if (vertex.words != 0)// 如果是一个单词,则返回return s;else// 如果不是一个单词则返回nullreturn null;} else {if (vertex.words != 0)temp = s;s += c;vertex = vertex.edges[index];}}// trie中存在比指定单词更长(包含指定词)的单词if (vertex.words == 0)//return temp;return s;}public static void main(String args[]) // Just used for test{Trie trie = new Trie();trie.addWord("abcedfddddddd");trie.addWord("a");trie.addWord("ba");trie.addWord("abce");trie.addWord("abcedfdddd");trie.addWord("abcef");String maxMatch = trie.getMaxMatchWord("abcedfddd");System.out.println(maxMatch);// List<String> list = trie.listAllWords();// Iterator listiterator = list.listIterator();// while (listiterator.hasNext()) {// String s = (String) listiterator.next();// System.out.println(s);// }// int count = trie.countPrefixes("abcdef");// int count1 = trie.countWords("abcd");// System.out.println("prefixes:" + count);// System.out.println("countWords:" + count1);}
}

  

最近开始慢慢了解中文分词技术,刚开始当然就是最大匹配了,之前做了一个非常简单的算法,字典存储在hashSet中,每次正向或逆向做最大切分N(字典中最长词组的长度,取N个字符),不匹配则取(N-1)个字符,继续匹配,如此循环只到匹配字典中的一个单词或者被切分成单字(1个字符)为止。例如我找的一个词典最长词组的长度为16,然后中文词组普遍是二字或三字词语,这里每切分一个词就白白多匹配了10多次。效率明显会有问题。

那么有什么好的方式可以解决这个问题呢? 首先想到的是字典的存储方式导致了这一问题。那么Trie树是如何解决这个问题的呢?

首先,我们可以将一段文字按照标点切分成句子(文章 -》段落 -》 句子 -》词组 ),然后将句子在字典(trie树)里做最大匹配(或者找出所有前缀匹配,做最优选择)进行切分,这么一来,就可以避免多次匹配,提高效率。

不过上面的代码,是针对英文的(为了简单起见),然后如果是中文,那么这棵trie会非常扁平(root下将出现成千上万的子节点),这个地方将会发生比较大的效率问题(查找效率),那么可以进行划分,例如将中文里的词语按照首字的首字母进行划分(或者其他方式),形成一个森林,然后用一个关联表进行对应。

Trie树实现[ java ]相关推荐

  1. 双数组Trie树(DoubleArrayTrie)Java实现

    http://www.hankcs.com/program/java/%E5%8F%8C%E6%95%B0%E7%BB%84trie%E6%A0%91doublearraytriejava%E5%AE ...

  2. trie树java_【数据结构】Trie树的应用:查询IP地址的ISP(Java实现)

    查询IP地址的ISP 给定一个IP地址,如何查询其所属的ISP,如:中国移动(ChinaMobile),中国电信(ChinaTelecom),中国铁通(ChinaTietong)? 现在网上有ISP的 ...

  3. Trie树进阶:Double-Array Trie原理及状态转移过程详解

    前言: Trie树本身就是一个很迷人的数据结构,何况是其改进的方案. 在本博客中我会从DAT(Double-Array Tire)的原理开始,并结合其源代码对DAT的状态转移过程进行解析.如果因此你能 ...

  4. 数据之美之Trie树

    原博客地址:http://blog.csdn.net/nash_/article/details/8227610 Trie树(又叫字典树,前缀树,单词查找树,键树)是一种树形数据结构,直接来看图: 我 ...

  5. 字典树(Trie)的java实现

    一.定义 字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用 ...

  6. java单词匹配算法_前端学数据结构与算法(八): 单词前缀匹配神器-Trie树的实现及其应用...

    前言 继二叉树.堆之后,接下来介绍另外一种树型的数据结构-Trie树,也可以叫它前缀树.字典树.例如我们再搜索引擎里输入几个关键字之后,后续的内容会自动续上.此时我们输入的关键词也就是前缀,而后面的就 ...

  7. java工具:字典树(单词查找树/Trie树)的实现以及使用

    项目地址 https://github.com/kylin-hunter/k-dic 文章目录 项目地址 前言 一.字典树 二.使用步骤 1 引入库 1.1 编译并发布到本地 1.2 gradle ( ...

  8. 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树......

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 上篇文章我们主要介绍了线性数据结构,本篇233酱带大家看看 无所不 ...

  9. 怎样实现基于Trie树和字典的分词功能

    前言 目前做分词比较流行的是用深度学习来做,比如用循环神经网络和条件随机场,也有直接用条件随机场或隐马尔科夫模型的.前面也实现过上面几种,效果挺不错,基于隐马尔科夫模型的差一点,条件随机场的效果较好, ...

最新文章

  1. 基于卷积神经网络(CNN)的仙人掌图像分类
  2. powerbook g4装linux,揭秘:服务器操作系统Linux版本发行
  3. 小伙伴们惊呆了!10行 JavaScript 实现文本编辑器
  4. SQL 去除重复记录 只保留重复记录中的一条
  5. ABAP中有关于换行符,TAB KEY等
  6. dtrace-stap-book
  7. 改造Python中文拼音扩展库pypinyin补充自定义声母全过程
  8. linux m530显卡,M530显卡和MX150哪个好(AMD Radeon M530)
  9. putty 使用perm密钥文件登陆堡垒机
  10. Python自学教程第2期-求100以内奇数和
  11. 编程:中国有句俗话“三天打鱼两天晒网”,某人从1990年1月1日起三天打鱼两天晒网,编程计算他在某一天是打鱼还是晒网
  12. python策略模式的应用_策略模式-Python四种实现方式
  13. 游戏和股票的结构有一定的类似性
  14. 树莓派开箱点亮(无屏幕)
  15. HTML5:移动端开发入门
  16. java模拟网易邮箱登录_java实现163邮箱发送邮件到qq邮箱成功案例
  17. dst发育筛查有意义吗_Dst发育筛查是什么?
  18. Python数据挖掘—电力窃漏电用户自动识别
  19. 本博客搜索,因为csdn的搜索功能不好使,所以使用google做个搜索
  20. 【Tensorflow2.x学习笔记】- 神经网络

热门文章

  1. Eclipse SQLExplorer插件的安装和使用
  2. 为什么晚上咳嗽很厉害
  3. Oracle 函数大全(字符串函数,数学函数,日期函数,逻辑运算函数,其他函数)
  4. SpringMVC以及SSM整合
  5. Web移动适配笔记(ing)
  6. 通过IHttpHandler实现图片验证码
  7. sql截取字符串并把字符串插入到表中的存储过程
  8. android 倒计时的控件,以动画的形式平滑的完成数字的过度
  9. django数据查询之聚合查询和分组查询
  10. python is 和 == 的区别、解码和编码 小数据池