使用Tries自动完成

时间:2014-03-28 00:19:47

标签: java data-structures autocomplete trie

import java.util.ArrayList;


public class AutoComplete {
    boolean newWord = false;
    ArrayList<String> all = new ArrayList<String>();

    static TrieNode root = new TrieNode('!', false, null);

    void add(String s){
        TrieNode temp = root;
//      TrieNode parent = root;

        for(int i=0; i < s.length(); i++){
            int t = s.charAt(i);
            t = t - 97;
            while((temp.links[t]) != null && i < s.length()-1){

                temp = temp.links[t];
                t = s.charAt(++i);
                t = t - 97;

//              parent = temp;
            }
            if( i != s.length()-1){
                temp.links[t] = new TrieNode((char)(97+t), false, null);
//              parent = temp.links[t];
            }
            else{
                temp.links[t] = new TrieNode((char) (97+t), true, null);
//              parent = temp.links[t];         
            }
            temp = temp.links[t];
        }
    }

    void readTree(String find){
        int len = find.length();
        int i = 0;
        TrieNode temp = root;
        String match = "";
        while(i != len){
            int t = find.charAt(i);
            t = t - 97;
            temp = temp.links[t];
            if(temp == null)
                break;
            match = match + temp.letter;
            i++;
        }
        if(match.length() > 0)
            match = match.substring(0,match.length()-1);
        printAll(temp, match);
    }

    void printAll(TrieNode t, String parent){
        if(t== null)
            return;
        parent = parent + t.letter;
        if(t.fullWord){
            System.out.println(parent);
        }
        for(int i = 0; i < 26; i++){
            printAll(t.links[i], parent);
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        AutoComplete a = new AutoComplete();

        a.add("tea");
        a.add("team");
        a.add("teach");
        a.add("teacher");
        a.readTree("t");
    }

}

我正在尝试使用try实现自动完成功能,当trie中的元素从较低长度添加到较高长度时,它可以正常工作

如果我按此顺序添加元素

a.add("tea");
a.add("team");
a.add("teach");
a.add("teacher");

我得到了a.readTree("t");

的以下输出
tea
teach
teacher
team

但如果我按此顺序添加元素

a.add("teacher");
a.add("teach");
a.add("team");
a.add("tea");

我得到了a.readTree("t");

的以下输出
tea

最终工作解决方案

public class AutoComplete {
    void add(String s, TrieNode root){
        //To keep the root node intact
        TrieNode temp = root;

        //Iterate through each char in string s
        for(int i=0; i < s.length(); i++){
            //each character in string
            int t = s.charAt(i);
            //its corresponding value in array links 
            t = t - 'a';
            //if some part of string is already present in array then just loop through it except th
            while((temp.links[t]) != null && i < s.length()-1){
                //increment i since first char is present
                i = i +1;
                //increment in trie
                temp = temp.links[t];
                //go to next char in string and 
                //go to that char location in array
                t = s.charAt(i)- 'a';
            }
            //Add only till before the last character
            if( i < s.length()-1){
                temp.links[t] = new TrieNode((char)('a'+t), false);
            }
            //for last character of string
            else{
                // if last character is not present
                if(temp.links[t] == null){
                    temp.links[t] = new TrieNode((char) ('a'+t), true);                 
                }
                // if last character already exist
                else{
                    temp.links[t].fullWord = true;
                }
            }
            //increment the trie
            temp = temp.links[t];
        }
    }
    void readTree(String find, TrieNode root){
        //get length in len
        int len = find.length();
        int i = 0;
        TrieNode temp = root;
        //initialize string to store the result
        String match = "";
        while(i < len){
            //get first char of search string
            int t = find.charAt(i) - 'a';
            //go to its array location
            temp = temp.links[t];
            //location is null then break else continue
            if(temp == null)
                break;
            //keep appending the found char and increment the index
            match = match + temp.letter;
            i++;
        }
        //if suggestions exist
        if(match.length() > 0)
            //pass the match string except for the last element
            match = match.substring(0,match.length()-1);
        printAll(temp, match);
    }

    void printAll(TrieNode t, String parent){
        if(t== null)
            return;
        parent = parent + t.letter;
        if(t.fullWord){
            System.out.println(parent);
        }
        for(int i = 0; i < 26; i++){
            printAll(t.links[i], parent);
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TrieNode root = new TrieNode('!', false);
        AutoComplete a = new AutoComplete();

        a.add("tea", root);
        a.add("team", root);
        a.add("teach", root);
        a.add("teacher", root);
        a.readTree("t", root);
    }

}

2 个答案:

答案 0 :(得分:1)

问题在于:

else{ //i == s.length - 1
        temp.links[t] = new TrieNode((char) (97+t), true, null);      
    }

当您添加&#34; teach&#34;时,它将在char&#39; h中新建一个节点,它将取代节点&#39; h&#39;老师 你应该这样写:

else{ //i == s.length - 1
        if(temp.links[t] == null) {
            temp.links[t] = new TrieNode((char) (97+t), true, null);    
        } 
        else {
            // change the leaf tag from false to true 
        }
    }

答案 1 :(得分:0)

Trie的概念似乎很难在您的代码中捕获。很难分辨出forwhile循环的所有可能情况并且仍然可读。在&#34;让它运行,使它正确,使它快速&#34;你应该尽可能简化你的第一个实现。

鉴于向Trie添加字符串的顺序确实会影响您的查询结果,您的代码显然不会运行。为了使它尽可能简单,您只需要查看新添加的字符串的第一个字符,并根据您在root中找到的字符进行操作,然后使用递归。这可能会影响您的运行时间,但这只是您的第三个问题(在正确之后)。如果您没有向我们展示您希望如何实施TrieNode,那么在答案中会有太多更改。