Category: Trees
Topics: autocomplete, prefix queries, lexicographic search, spell checking
A tree-like data structure for storing strings where each node represents a character, enabling efficient prefix-based operations in O(L) time where L is the string length.
| Operation | Time | Description |
|---|---|---|
| Insert | O(L) | Add word of length L |
| Search | O(L) | Find exact word |
| Prefix search | O(P) | Check if prefix exists |
| Autocomplete | O(P+S) | Find S suggestions with prefix P |
| Delete | O(L) | Remove word |
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
"""Insert word - O(L)"""
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
def search(self, word):
"""Search exact word - O(L)"""
node = self._find_node(word)
return node is not None and node.is_end
def starts_with(self, prefix):
"""Check if any word starts with prefix - O(P)"""
return self._find_node(prefix) is not None
def _find_node(self, prefix):
node = self.root
for char in prefix:
if char not in node.children:
return None
node = node.children[char]
return node
def autocomplete(self, prefix):
"""Get all words with prefix - O(P + S)"""
node = self._find_node(prefix)
if not node:
return []
results = []
self._dfs(node, prefix, results)
return results
def _dfs(self, node, path, results):
if node.is_end:
results.append(path)
for char, child in node.children.items():
self._dfs(child, path + char, results)
# Usage
trie = Trie()
trie.insert("apple")
trie.insert("app")
trie.insert("application")
trie.search("app") # True
trie.starts_with("app") # True
trie.autocomplete("app") # ["app", "apple", "application"]
O(N * L) worst case where N is number of words and L is average length. With prefix sharing, actual space is often much less. Each node stores a hash map of children.
Pros:
Cons: