zoukankan      html  css  js  c++  java
  • Implement Trie and find longest prefix string list

      

      1 package leetcode;
      2 
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 
      6 class TrieNode{
      7     Boolean isWord;//true if path till this node represent a string. 
      8     Integer freq;//numbers of strings share the same prefix
      9     Character nodeChar;//character for this node
     10     ArrayList<TrieNode> childNodes;
     11     public TrieNode(char c){
     12         childNodes = new ArrayList<TrieNode>();
     13         this.nodeChar = c;
     14         this.freq = 1;
     15         this.isWord = false;
     16     }
     17     public TrieNode(){
     18         childNodes = new ArrayList<TrieNode>();
     19         this.nodeChar = null;
     20         this.freq = 0;
     21         this.isWord = false;
     22     }
     23 }
     24 
     25 class Prefix{
     26     TrieNode root;
     27     String prefix;
     28     public Prefix(TrieNode root, String s){
     29         this.root = root;
     30         this.prefix = s;
     31     }
     32 }
     33 
     34 public class Trie {
     35     /*
     36     Trie is an efficient information retrieval data structure. 
     37     Using trie, search complexities can be brought to optimal limit (key length). 
     38     If we store keys in binary search tree, a well balanced BST will need time proportional to M * log N, 
     39     where M is maximum string length and N is number of keys in tree. 
     40     Using trie, we can search the key in O(M) time. 
     41     However the penalty is on trie storage requirements.
     42     */
     43     TrieNode root;
     44     public Trie(){
     45         root = new TrieNode();
     46     }
     47 
     48     public void insert(String s){
     49         if(s == null || s.length() == 0) return;
     50         TrieNode tmp = root;
     51         tmp.freq ++;// prefix freq ++
     52         for(int i = 0; i < s.length(); i ++){
     53             Boolean hasNode = false;
     54             for(int j = 0; j < tmp.childNodes.size(); j ++){
     55                 if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
     56                     tmp = tmp.childNodes.get(j);
     57                     tmp.freq ++;
     58                     hasNode = true;
     59                     break;
     60                 }
     61             }
     62             if(hasNode == false){
     63                 TrieNode newNode = new TrieNode(s.charAt(i));
     64                 tmp.childNodes.add(newNode);
     65                 tmp = newNode;
     66             }
     67         }
     68         tmp.isWord = true;
     69     }
     70 
     71     public Boolean searchString(String s){
     72         if(s == null || s.length() == 0) return false;
     73         TrieNode tmp = root;
     74         for(int i = 0; i < s.length(); i ++){
     75             Boolean containsChar = false;
     76             for(int j = 0; j < tmp.childNodes.size(); j ++){
     77                 if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
     78                     tmp = tmp.childNodes.get(j);
     79                     containsChar = true;
     80                     break;
     81                 }
     82             }
     83             if(containsChar == false){
     84                 return false;
     85             }
     86         }
     87         return tmp.isWord == true;
     88     }
     89 
     90     /*
     91      * During delete operation we delete the key in bottom up manner using recursion. The following are possible conditions when deleting key from trie,
     92      * 1. Key may not be there in trie. Delete operation should not modify trie.
     93      * 2. Key present as unique key (no part of key contains another key (prefix), nor the key itself is prefix of another key in trie). Delete all the nodes.
     94      * 3. Key is prefix key of another long key in trie. Unmark the leaf node.
     95      * 4. Key present in trie, having atleast one other key as prefix key. Delete nodes from end of key until first leaf node of longest prefix key.
     96     */
     97     public void delete(String s){
     98         if(searchString(s) == false) return;
     99         TrieNode tmp = root;
    100         if(tmp.freq == 1){
    101             tmp.childNodes.remove(0);
    102             tmp.freq = 0;
    103             return;
    104         }
    105         for(int i = 0; i < s.length(); i ++){
    106             for(int j = 0; j < tmp.childNodes.size(); j ++){
    107                 if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
    108                     if(tmp.childNodes.get(j).freq == 1){
    109                         tmp.childNodes.remove(j);
    110                         tmp.freq --;
    111                         return;
    112                     }else{
    113                         tmp.childNodes.get(j).freq --;
    114                         tmp = tmp.childNodes.get(j);
    115                     }
    116                     break;
    117                 }
    118             }
    119         }
    120         tmp.isWord = false;
    121 
    122     }
    123 
    124     //find a list of string in the dictionary, which contains the longest prefix with the target string
    125     public List<String> findAllStringWithSameLongestPrefix(String s){
    126         Prefix tmp = findLongestPrefix(s);
    127         List<String> result = new ArrayList<String>();
    128         if(tmp.root.equals(root)) return result;
    129         findAllStringInSubTree(tmp.root, new StringBuilder(tmp.prefix), result);
    130         return result;
    131     }
    132 
    133     private Prefix findLongestPrefix(String s){
    134         TrieNode tmp = root;
    135         StringBuilder sb = new StringBuilder();
    136         for(int i = 0; i < s.length(); i ++){
    137             Boolean containsChar = false;
    138             for(int j = 0; j < tmp.childNodes.size(); j ++){
    139                 if(tmp.childNodes.get(j).nodeChar == s.charAt(i)){
    140                     sb.append(s.charAt(i));
    141                     tmp = tmp.childNodes.get(j);
    142                     containsChar = true;
    143                     break;
    144                 }
    145             }
    146             if(containsChar == false){
    147                 return new Prefix(tmp, sb.toString());
    148             }
    149         }
    150         return new Prefix(tmp, s);
    151     }
    152 
    153     private void findAllStringInSubTree(TrieNode root, StringBuilder sb, List<String> result){
    154         if(root.isWord == true){
    155             result.add(sb.toString());
    156         }
    157         for(int i = 0; i < root.childNodes.size(); i ++){
    158             TrieNode tmp = root.childNodes.get(i);
    159             sb.append(tmp.nodeChar);
    160             findAllStringInSubTree(tmp, new StringBuilder(sb), result);
    161             sb.deleteCharAt(sb.length() - 1);
    162         }
    163     }
    164     
    165     public static void main(String[] args){
    166         Trie trie = new Trie();
    167         System.out.println("insert string into Trie:");
    168         System.out.println("a, aq, ab, abb, aa, bbd, bd, ba, abc");
    169         trie.insert("a");
    170         trie.insert("aq");
    171         trie.insert("ab");
    172         trie.insert("abb");
    173         trie.insert("aa");
    174         trie.insert("bbd");
    175         trie.insert("bd");
    176         trie.insert("ba");
    177         trie.insert("abc");
    178         System.out.println("search string in Trie:");
    179         System.out.println("abb: " + trie.searchString("abb"));
    180         System.out.println("bd: " + trie.searchString("bd"));
    181         System.out.println("bda: " + trie.searchString("bda"));
    182         System.out.println("strings start with a:");
    183         List<String> list1 = trie.findAllStringWithSameLongestPrefix("a");
    184         for(int i = 0; i < list1.size(); i ++){
    185             System.out.println(list1.get(i));
    186         }
    187         System.out.println("strings start with b:");
    188         List<String> list2 = trie.findAllStringWithSameLongestPrefix("b");
    189         for(int i = 0; list2 != null && i < list2.size(); i ++){
    190             System.out.println(list2.get(i));
    191         }
    192         System.out.println("strings start with ab:");
    193         List<String> list3 = trie.findAllStringWithSameLongestPrefix("ab");
    194         for(int i = 0; i < list3.size(); i ++){
    195             System.out.println(list3.get(i));
    196         }
    197         System.out.println("strings start with abcdef:");
    198         List<String> list4 = trie.findAllStringWithSameLongestPrefix("abcdef");
    199         for(int i = 0; list4 != null && i < list4.size(); i ++){
    200             System.out.println(list4.get(i));
    201         }
    202         System.out.println("delete string from trie:");
    203         trie.delete("ab");
    204         System.out.println(trie.searchString("ab"));
    205         System.out.println(trie.searchString("abb"));
    206     }
    207 }

    Output:

    insert string into Trie:
    a, aq, ab, abb, aa, bbd, bd, ba, abc
    search string in Trie:
    abb: true
    bd: true
    bda: false
    strings start with a:
    a
    aq
    ab
    abb
    abc
    aa
    strings start with b:
    bbd
    bd
    ba
    strings start with ab:
    ab
    abb
    abc
    strings start with abcdef:
    abc
    delete string from trie:
    false
    true
  • 相关阅读:
    使用iOS网络请求
    Invalid RNPermission 'ios.permission.xxx'. should be one of: ( )
    React Native 报错 Error: spawn EACCES 权限
    React Native 适配Android物理返回键,实现连续两次点击退出
    图解:平衡二叉树,AVL树
    NOIP 骗分技巧
    P1004 方格取数
    5. 最长回文子串
    全链路压测自动化实践
    深度学习在美团配送ETA预估中的探索与实践
  • 原文地址:https://www.cnblogs.com/reynold-lei/p/4377043.html
Copyright © 2011-2022 走看看