Trie Tree 实现中文分词器
前言
繼上一篇HashMap實現中文分詞器后,對Trie Tree的好奇,又使用Trie Tree實現了下中文分詞器。效率比HashMap實現的分詞器更高。
Trie Tree 簡介
Trie Tree,又稱單詞字典樹、查找樹,是一種樹形結構,是一種哈希樹的變種。典型應用是用于統計和排序大量的字符串(但不僅限于字符串),所以經常被搜索引擎系統用于文本詞頻統計。它的優點是:最大限度地減少無謂的字符串比較,查詢效率比哈希表高。
性質
它有3個基本性質:
1. 根節點不包含字符,除根節點外每一個節點都只包含一個字符。
2. 從根節點到某一節點,路徑上經過的字符連接起來,為該節點對應的字符串。
3. 每個節點的所有子節點包含的字符都不相同。
Trie Tree 結構
Trie Tree分詞原理:
(1) 從根結點開始一次搜索,比如搜索【北京】;
(2) 取得要查找關鍵詞的第一個字符【北】,并根據該字符選擇對應的子樹并轉到該子樹繼續進行檢索;
(3) 在相應的子樹上,取得要查找關鍵詞的第二個字符【京】,并進一步選擇對應的子樹進行檢索。
(4) 迭代過程……
(5) 在直到判斷樹節點的isEnd節點為true則查找結束(最小匹配原則),然后發現【京】isEnd=true,則結束查找。
示例
下面用java簡單實現
package cn.com.infcn.algorithm;import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry;/*** jijs* 正向最大匹配*/ public class TrieTreeDemo {static class Node {//記錄當前節點的字char c;//判斷該字是否詞語的末尾,如果是則為falseboolean isEnd;//子節點List<Node> childList;public Node(char c) {super();this.c = c;isEnd = false;childList = new LinkedList<Node>();}//查找當前子節點中是否保護c的節點public Node findNode(char c){for(Node node : childList){if(node.c == c){return node;}}return null;}}static class TrieTree{Node root = new Node(' ');//構建Trie Treepublic void insert(String words){char[] arr = words.toCharArray();Node currentNode = root;for (char c : arr) {Node node = currentNode.findNode(c);//如果不存在該節點則添加if(node == null){Node n = new Node(c);currentNode.childList.add(n);currentNode = n;}else{currentNode = node;}}//在詞的最后一個字節點標記為truecurrentNode.isEnd = true;}//判斷Trie Tree中是否包含該詞public boolean search(String word){char[] arr = word.toCharArray();Node currentNode = root;for (int i=0; i<arr.length; i++) {Node n = currentNode.findNode(arr[i]);if(n != null){currentNode = n;//判斷是否為詞的尾節點節點if(n.isEnd){if(n.c == arr[arr.length-1]){return true;}}}}return false;}//最大匹配優先原則public Map<String, Integer> tokenizer(String words){char[] arr = words.toCharArray();Node currentNode = root;Map<String, Integer> map = new HashMap<String, Integer>();//記錄Trie Tree 從root開始匹配的所有字StringBuilder sb = new StringBuilder();;//最后一次匹配到的詞,最大匹配原則,可能會匹配到多個字,以最長的那個為準String word="";//記錄記錄最后一次匹配坐標int idx = 0;for (int i=0; i<arr.length; i++) {Node n = currentNode.findNode(arr[i]);if(n != null){sb.append(n.c);currentNode = n;//匹配到詞if(n.isEnd){//記錄最后一次匹配的詞word = sb.toString();//記錄最后一次匹配坐標idx = i;}}else{//判斷word是否有值if(word!=null && word.length()>0){Integer num = map.get(word);if(num==null){map.put(word, 1);}else{map.put(word, num+1);}//i回退到最后匹配的坐標i=idx;//從root的開始匹配currentNode = root;//清空匹配到的詞word = null;//清空當前路徑匹配到的所有字sb = new StringBuilder();}}if(i==arr.length-2){if(word!=null && word.length()>0){Integer num = map.get(word);if(num==null){map.put(word, 1);}else{map.put(word, num+1);}}}}return map;}}public static void main(String[] args) {TrieTree tree = new TrieTree();tree.insert("北京");tree.insert("海淀區");tree.insert("中國");tree.insert("中國人民");tree.insert("中關村");String word = "中國";//查找該詞是否存在 Trid Tree 中boolean flag = tree.search(word);if(flag){System.out.println("Trie Tree 中已經存在【"+word+"】");}else{System.out.println("Trie Tree 不包含【"+word+"】");}//分詞Map<String, Integer> map = tree.tokenizer("中國人民,中國首都是北京,中關村在海淀區,中國北京天安門。中國人");for (Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey()+":"+entry.getValue());}} }想了解更多精彩內容請關注我的公眾號
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
GIT地址:http://git.oschina.net/brucekankan/
點擊這里快速進入GIT
總結
以上是生活随笔為你收集整理的Trie Tree 实现中文分词器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 成神之路
- 下一篇: 深入分析JVM逃逸分析对性能的影响