import java.util.*;
class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
boolean isWord = false;
}
class AutocompleteSystem {
private final TrieNode root = new TrieNode();
// Insert a word into the trie
public void insert(String word) {
TrieNode curr = root;
for (char ch : word.toCharArray()) {
curr.children.putIfAbsent(ch, new TrieNode()); // create node if missing
curr = curr.children.get(ch); // move to next node
}
curr.isWord = true; // mark end of word
}
// Search all words with given prefix
public List<String> autocomplete(String prefix) {
List<String> results = new ArrayList<>();
TrieNode curr = root;
for (char ch : prefix.toCharArray()) {
if (!curr.children.containsKey(ch)) {
return results; // prefix not found
}
curr = curr.children.get(ch); // move to prefix end
}
dfs(curr, new StringBuilder(prefix), results); // collect words
return results;
}
// Depth-first search to collect words
private void dfs(TrieNode node, StringBuilder path, List<String> results) {
if (node.isWord) {
results.add(path.toString()); // found a word
}
for (Map.Entry<Character, TrieNode> entry : node.children.entrySet()) {
path.append(entry.getKey()); // add letter
dfs(entry.getValue(), path, results); // recurse
path.deleteCharAt(path.length() - 1); // backtrack
}
}
public static void main(String[] args) {
AutocompleteSystem ac = new AutocompleteSystem();
String[] words = {"cat", "car", "cart"};
for (String w : words) {
ac.insert(w);
}
List<String> completions = ac.autocomplete("ca");
System.out.println(completions);
}
}curr.children.putIfAbsent(ch, new TrieNode());
create child node if missing to build word path
curr = curr.children.get(ch);
advance current node to next letter node
mark node as end of a valid word
if (!curr.children.containsKey(ch)) { return results; }
stop search if prefix letter missing
dfs(curr, new StringBuilder(prefix), results);
start collecting all words below prefix node
if (node.isWord) { results.add(path.toString()); }
add complete word to results when end node reached
path.append(entry.getKey()); dfs(entry.getValue(), path, results); path.deleteCharAt(path.length() - 1);
explore each child node recursively and backtrack