Skip to main content

Guidelines

Trie are probably one of the most straighforward patterns to spot since your first hint when working with strings, suffix, prefix should be to use trie data structure. Below we list implementation of basic implementation for trie.

class Trie {
private class TrieNode{
TrieNode[] children;
boolean isWord = false;
public TrieNode(){
children = new TrieNode[26];
}
}

TrieNode root;
public Trie() {
root = new TrieNode();
}

private TrieNode searchPrefix(String prefix){
TrieNode iter = root;
for(int i = 0; i < prefix.length(); ++i){
char letter = prefix.charAt(i);
if(iter.children[letter - 'a'] == null){
return null;
}
iter = iter.children[letter - 'a'];
}
return iter;
}

public void insert(String word) {
TrieNode iter = root;
for(int i = 0; i < word.length(); ++i){
char letter = word.charAt(i);
if(iter.children[letter - 'a'] == null){
iter.children[letter - 'a'] = new TrieNode();
}
iter = iter.children[letter - 'a'];
}
iter.isWord = true;
}

public boolean search(String word) {
TrieNode node = searchPrefix(word);
return node != null && node.isWord;
}

public boolean startsWith(String prefix) {
return searchPrefix(prefix) != null;
}
}

There are two things you have to modify to fit this implementation to any trie problem:

  • What additional info will you store (e.g. isWord, word, index).
  • Modification on search and insert to adjust to the problem statement. Most of the times you will have far more read queries than writes/building the trie, so extra space and time can be used on the building trie, so we can reduce time on reading/searching queries.