Longest Word with All Prefixes
Among a list of words, find the longest word whose every prefix is also a word in the list. Ties are broken alphabetically.
Open on GeeksforGeeks ↗Intuition
The condition is about every prefix of a word, and a trie is precisely the structure where a word's prefixes are the nodes along its path. Insert everything, flagging each node that terminates a real word. Then a word qualifies if and only if every node on its path carries that flag — one walk per word, no repeated string slicing. Scanning candidates in sorted order makes the tie-break free: the first word to reach a new maximum length is already the alphabetically smallest of that length.
Build a trie of every word, then re-walk each word checking that every node along its path is marked as a word end. That verifies all prefixes exist in one descent instead of doing a separate lookup per prefix. Sorting first makes the lexicographic tiebreak fall out without comparing strings explicitly.
Approach
Build the trie with end flags
Insert every word; mark the final node of each with an end-of-word flag. Shared prefixes share nodes automatically.
Validate by walking
For a candidate word, walk its path and require the end flag at every single node. The first unflagged node disqualifies it immediately.
Sort to make ties free
Process candidates alphabetically and keep a strictly-longer rule. The alphabetical winner is then found without an explicit comparison.
Solution & live demo
Common pitfalls
Checking each prefix with a separate lookup
if all(w[:i] in word_set for i in range(1, len(w) + 1)):
for ch in w:
node = node[ch]
if "$" not in node: ok = False; breakThat slices and hashes a new string for every prefix — O(L²) per word. Walking the trie visits each prefix's node exactly once as a by-product of the descent.
Ignoring the lexicographic tiebreak
for w in words:
if ok and len(w) > len(best): best = wfor w in sorted(words):
...When several valid words share the maximum length, the problem asks for the lexicographically smallest. Iterating in sorted order means the first one of that length wins and > never replaces it.
Testing the final node only
if "$" in node: ok = True
if "$" not in node:
ok = False
breakThat only confirms the word itself is present, which is trivially true. The requirement is that every prefix is also a word, so the check belongs at each step of the walk.
Edge cases
Every candidate breaks at some prefix, so the answer is the empty string.
The only prefix is the word itself, so any length-1 word trivially qualifies.
Sorted order visits the alphabetically smaller first, and the strict length comparison prevents the later one from replacing it.