A prefix tree: each edge is a character, so shared prefixes are stored once.
Reach for it when
Prefix queries (startsWith, autocomplete)
Many words searched in a grid or a stream
Wildcard matching over a dictionary
Core idea
Each node holds a map from character to child plus an end-of-word flag. Insert and search cost O(length of word), independent of how many words are stored, and a DFS over the trie can prune an entire set of words the moment a prefix fails.
Template · O(L) per operation, O(total characters) space
classTrie:
def__init__(self):
self.root = {}
definsert(self, word):
node =self.root
for ch in word:
node = node.setdefault(ch, {})
node["$"] =True# end of word
defstarts_with(self, prefix):
node =self.root
for ch in prefix:
if ch notin node:
returnFalse
node = node[ch]
returnTrue
structTrie {
structNode { array<Node*, 26> next{}; bool end =false; };
Node* root =newNode();
voidinsert(conststring&word) {
Node* node = root;
for (char ch : word) {
Node*& child = node->next[ch -'a'];
if (!child) child =newNode();
node = child;
}
node->end =true; // end of word
}
boolstartsWith(conststring&prefix) {
Node* node = root;
for (char ch : prefix) {
node = node->next[ch -'a'];
if (!node) returnfalse;
}
returntrue;
}
};
Common pitfalls
Forgetting the end-of-word marker (prefix vs word)
In Word Search II, remove found words to avoid duplicates