我正在进行这项实现自动完成和字典的任务。我已成功实现了拼写检查以及addWord()和isWord()函数。 但我只是无法实现为AutoCompletions预测单词的函数。
package spelling;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
/**
* An trie data structure that implements the Dictionary and the AutoComplete ADT
* @author You
*
*/
public class AutoCompleteDictionaryTrie implements Dictionary, AutoComplete {
private TrieNode root;
private int size;
public AutoCompleteDictionaryTrie()
{
root = new TrieNode();
size=0;
}
/** Insert a word into the trie.
* For the basic part of the assignment (part 2), you should ignore the word's case.
* That is, you should convert the string to all lower case as you insert it. */
public boolean addWord(String word)
{
//TODO: Implement this method.
String Word=word.toLowerCase();
if(isWord(Word))
return false;
HashMap<Character, TrieNode> children=root.children;
for(int i=0; i<Word.length(); i++){
char c = Word.charAt(i);
TrieNode t;
if(children.containsKey(c)){
t = children.get(c);
}else{
t = new TrieNode(""+(c));
children.put(c, t);
}
children = t.children;
if(i==Word.length()-1)
{
t.isWord = true;
size++;
}
}
return true;
}
/**
* Return the number of words in the dictionary. This is NOT necessarily the same
* as the number of TrieNodes in the trie.
*/
public int size()
{
//TODO: Implement this method
return size;
}
/** Returns whether the string is a word in the trie */
@Override
public boolean isWord(String s)
{
// TODO: Implement this method
TrieNode t = searchNode(s.toLowerCase());
if(t != null && t.isWord)
return true;
else
return false;
}
public TrieNode searchNode(String str){
HashMap<Character, TrieNode> children = root.children;
TrieNode t = null;
for(int i=0; i<str.length(); i++){
char c = str.charAt(i);
if(children.containsKey(c)){
t = children.get(c);
children = t.children;
}else{
return null;
}
}
return t;
}
/**
* * Returns up to the n "best" predictions, including the word itself,
* in terms of length
* If this string is not in the trie, it returns null.
* @param text The text to use at the word stem
* @param n The maximum number of predictions desired.
* @return A list containing the up to n best predictions
*/@Override
public List<String> predictCompletions(String prefix, int numCompletions)
{
// TODO: Implement this method
// This method should implement the following algorithm:
// 1. Find the stem in the trie. If the stem does not appear in the trie, return an
// empty list
// 2. Once the stem is found, perform a breadth first search to generate completions
// using the following algorithm:
// Create a queue (LinkedList) and add the node that completes the stem to the back
// of the list.
// Create a list of completions to return (initially empty)
// While the queue is not empty and you don't have enough completions:
// remove the first Node from the queue
// If it is a word, add it to the completions list
// Add all of its child nodes to the back of the queue
// Return the list of completions
List<String> completions=null;
int counter=0;
if (prefix==null){
return Collections.emptyList();
}
prefix=prefix.toLowerCase();
if(isWord(prefix))
completions.add(prefix);
LinkedList nodes = new LinkedList();
TrieNode curr=searchNode(prefix);
nodes.addLast(curr);
while(!nodes.isEmpty() && counter!=numCompletions)
{
if((nodes.removeFirst()).isWord)
completions.add(curr.getText());
TrieNode next = null;
for (Character c : curr.getValidNextCharacters()) {
next = curr.getChild(c);
}
}
return Collections.emptyList();
}
public void checkNull(String word){
if (word==null)
throw new NullPointerException("Null word passed");
}
// For debugging
public void printTree()
{
printNode(root);
}
/** Do a pre-order traversal from this node down */
public void printNode(TrieNode curr)
{
if (curr == null)
return;
System.out.println(curr.getText());
TrieNode next = null;
for (Character c : curr.getValidNextCharacters()) {
next = curr.getChild(c);
printNode(next);
}
}
}
这是TrieNode类的代码:
package spelling;
import java.util.HashMap;
import java.util.Set;
/**
* Represents a node in a Trie
* @author UC San Diego Intermediate Programming MOOC Team
*
*/
class TrieNode {
HashMap<Character, TrieNode> children;
private String text; // Maybe omit for space
boolean isWord;
/** Create a new TrieNode */
public TrieNode()
{
children = new HashMap<Character, TrieNode>();
text = "";
isWord = false;
}
/** Create a new TrieNode given a text String to store in it */
public TrieNode(String text)
{
this();
this.text = text;
}
/** Return the TrieNode that is the child when you follow the
* link from the given Character
* @param c The next character in the key
* @return The TrieNode that character links to, or null if that link
* is not in the trie.
*/
public TrieNode getChild(Character c)
{
return children.get(c);
}
/** Inserts this character at this node.
* Returns the newly created node, if c wasn't already
* in the trie. If it was, it does not modify the trie
* and returns null.
* @param c The character that will link to the new node
* @return The newly created TrieNode, or null if the node is already
* in the trie.
*/
public TrieNode insert(Character c)
{
if (children.containsKey(c)) {
return null;
}
TrieNode next = new TrieNode(text + c.toString());
children.put(c, next);
return next;
}
/** Return the text string at this node */
public String getText()
{
return text;
}
/** Set whether or not this node ends a word in the trie. */
public void setEndsWord(boolean b)
{
isWord = b;
}
/** Return whether or not this node ends a word in the trie. */
public boolean endsWord()
{
return isWord;
}
/** Return the set of characters that have links from this node */
public Set<Character> getValidNextCharacters()
{
return children.keySet();
}
}
即使算法在那里,我也无法实现它。任何形式的帮助将不胜感激。
答案 0 :(得分:3)
//Trying to find the stem in Trie
String prefixToCheckLowerCase = prefix.toLowerCase();
int completionsCount = 0;
List<String> completions = new LinkedList<String>();
TrieNode traversal = root;
for (int i = 0; i < prefixToCheckLowerCase.length(); i++)
{
if (traversal.getValidNextCharacters().contains(prefixToCheckLowerCase.charAt(i)))
{
traversal = traversal.getChild(prefixToCheckLowerCase.charAt(i));
}
//Means stem not found, returns an empty list
else
return completions;
}
//If current word is an end word, increment the counter and add it to compeltions list
if (traversal.endsWord())
{
completionsCount=1;
completions.add(traversal.getText());
}
List<TrieNode> nodesToBeSearched = new LinkedList<TrieNode>();
List<Character> ChildCharaterList = new LinkedList<Character>(traversal.getValidNextCharacters());
//Filling the list with children of the current node, first level of of the breadth first search
for (int i=0; i<ChildCharaterList.size(); i++)
{
nodesToBeSearched.add(traversal.getChild(ChildCharaterList.get(i)));
}
//while loop for the linked list elements and see if any compeltions exists , inside it we will also check each node children and add them to the list!!!
while (nodesToBeSearched!=null && nodesToBeSearched.size()>0 && completionsCount < numCompletions)
{
TrieNode trieNode = nodesToBeSearched.remove(0);
if (trieNode.endsWord())
{
completionsCount++;
completions.add(trieNode.getText());
}
List<Character> subTrieNodeCholdren = new LinkedList<Character>(trieNode.getValidNextCharacters());
//Adding all next level tries to the linked list , kinda recursive!!!
for (int i=0; i<subTrieNodeCholdren.size();i++)
{
nodesToBeSearched.add(trieNode.getChild(subTrieNodeCholdren.get(i)));
}
}
return completions;
答案 1 :(得分:0)
import java.util.ArrayList;
class TrieNode{
char data;
boolean isTerminating;
TrieNode children[];
int childCount;
public TrieNode(char data) {
this.data = data;
isTerminating = false;
children = new TrieNode[26];
childCount = 0;
}
}
public class Trie {
private TrieNode root;
//ArrayList<String> ans=new ArrayList<>();
public Trie() {
root = new TrieNode('\0');
}
private void add(TrieNode root, String word){
if(word.length() == 0){
root.isTerminating = true;
return;
}
int childIndex = word.charAt(0) - 'a';
TrieNode child = root.children[childIndex];
if(child == null){
child = new TrieNode(word.charAt(0));
root.children[childIndex] = child;
root.childCount++;
}
add(child, word.substring(1));
}
public void add(String word){
add(root, word);
}
private void searchHelper(TrieNode root,String word,String ans)
{
try
{
if(word.length()==0)
{
if(root.isTerminating == true)
{
System.out.println(ans);
}
for(int i=0;i<26;i++)
{
TrieNode temp=root.children[i];
if(temp !=null)
{
//ans=ans+temp.data;
//System.out.println("test check "+ans );
searchHelper(temp,word,ans+temp.data);
}
}
}
int childIndex=word.charAt(0)-'a';
TrieNode child=root.children[childIndex];
if(child == null)
{
//System.out.print();
return ;
}
ans=ans+word.charAt(0);
searchHelper(child,word.substring(1),ans);
}
catch(Exception e)
{
//System.out.println("error");
}
}
public void search(String word)
{
String s="";
searchHelper(root,word,s);
}
public void autoComplete(ArrayList<String> input, String word) {
// Complete this function
// Print the output as specified in question
Trie ansTrie = new Trie();
for(int i=0;i<input.size();i++)
{
ansTrie.add(input.get(i));
}
ansTrie.search(word);
}
}
我希望它有助于解决您的疑问。 我已经为任何缩进错误感到抱歉。