Skip to main content

Trie

A trie (prefix tree) is a rooted tree in which every edge is labelled by a single character and every path from the root to a marked node spells out a stored string. Sibling edges carry distinct labels, so at each node we can branch on the next character in O(1)O(1) using a dictionary or fixed-size array. Inserting or querying a word of length LL touches exactly LL nodes regardless of how many other words are stored, which makes tries attractive for dictionary-heavy workloads and prefix autocomplete.

The example supports three operations: insert a word during construction, then answer queries of the form ["search", s] (is ss a stored word?) or ["starts_with", s] (does any stored word start with ss?).

Codes​

class Trie:
def __init__(self):
self.children = {}
self.end = False

def insert(self, word):
node = self
for ch in word:
node = node.children.setdefault(ch, Trie())
node.end = True

def _walk(self, s):
node = self
for ch in s:
if ch not in node.children:
return None
node = node.children[ch]
return node

def search(self, s):
node = self._walk(s)
return node is not None and node.end

def starts_with(self, s):
return self._walk(s) is not None


def solve(xs):
words, queries = xs
trie = Trie()
for w in words:
trie.insert(w)
answers = []
for q in queries:
kind, s = q[0], q[1]
if kind == "search":
answers.append(trie.search(s))
else:
answers.append(trie.starts_with(s))
return answers

Example​

Loading Python runner...

Description​

Run time analysis​

O(L)O(L) per insert, search, or prefix query, where LL is the length of the input string. Each step descends one level of the trie and does a constant amount of dictionary work. Building the trie from a word list of total length NN takes O(N)O(N).

Space analysis​

O(Nσ)O(N \sigma) in the worst case for NN total characters across all stored words and an alphabet of size σ\sigma. With hash-map children the constant is much smaller in practice because only the characters that actually occur at each node allocate a slot.

Proof of correctness​

The root-to-node path labels of a trie are a prefix-closed set of strings. insert(word) extends the path for word one character at a time, creating missing children as needed, and finally sets the terminal flag on the last node — so after insertion, the walk for any prefix of word lands on an existing node, and the walk for word itself lands on a node with the terminal flag set. _walk(s) returns the node reached by ss if the path exists and None otherwise. Therefore search(s) is true exactly when some previously inserted word equals ss, and starts_with(s) is true exactly when some previously inserted word has ss as a prefix.

Extensions​

Applications​

References​