Skip to content

Tries and String Algorithms

A trie is a tree data structure where each node represents a character of a string. The path from The root to any node spells out a prefix, and nodes marked as “end of word” represent complete Strings in the set.

class TrieNode:
__slots__ = ("children', 'is_end', 'word')
def __init__(self):
self.children = {}
self.is_end = False
self.word = None
class Trie:
"""
Trie (prefix tree) for string storage and retrieval.
Insert: O(m) where m = length of word
Search: O(m)
StartsWith: O(m)
Space: O(ALPHABET_SIZE * total_characters)
"""
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for ch in word:
if ch not in node.children:
node.children[ch] = TrieNode()
node = node.children[ch]
node.is_end = True
node.word = word
def search(self, word):
node = self.root
for ch in word:
if ch not in node.children:
return False
node = node.children[ch]
return node.is_end
def starts_with(self, prefix):
node = self.root
for ch in prefix:
if ch not in node.children:
return False
node = node.children[ch]
return True
def delete(self, word):
def _delete(node, word, depth):
if not node:
return False
if depth == len(word):
if not node.is_end:
return False
node.is_end = False
return len(node.children) == 0
ch = word[depth]
if ch not in node.children:
return False
should_delete = _delete(node.children[ch], word, depth + 1)
if should_delete:
del node.children[ch]
return len(node.children) == 0 and not node.is_end
return False
_delete(self.root, word, 0)
def words_with_prefix(self, prefix):
"""Collect all words with given prefix. Time: O(m + k * L) where k = results."""
node = self.root
for ch in prefix:
if ch not in node.children:
return []
node = node.children[ch]
results = []
def _collect(n):
if n.is_end:
results.append(n.word)
for ch, child in n.children.items():
_collect(child)
_collect(node)
return results
graph TD
    ROOT["root"] --> A["a"]
    A --> P["p"]
    A --> PP["pp"]
    A --> D["d"]
    P --> P2["p"]
    P --> P3["p"]
    P --> L["l"]
    P2 --> L2["l"]
    P2 --> E["e"]
    P3 --> E2["e"]
    L --> E3["e"]
    D --> D2["d"]
    D --> D3["d"]
    D2 --> E4["e"]
    D3 --> E5["e"]

    style ROOT fill:#95a5a6,color:#fff
    style P2 fill:#e74c3c,color:#fff
    style E fill:#e74c3c,color:#fff
    style L2 fill:#e74c3c,color:#fff
    style E4 fill:#e74c3c,color:#fff
    style E5 fill:#e74c3c,color:#fff
OperationTimeSpace
InsertO(m)O(m)O(1)O(1) additional nodes
SearchO(m)O(m)O(1)O(1)
DeleteO(m)O(m)O(1)O(1) freed nodes
StartsWithO(m)O(m)O(1)O(1)
Prefix searchO(m+kL)O(m + kL)O(kL)O(kL) for results

Where mm is the word length, kk is the number of results, and LL is the average result length.