We have a list of words and need to find the longest one that has a complete "chain" of prefixes in the dictionary. For a word like "world" to be valid, the dictionary must also contain "w", "wo", "wor", and "worl". Each prefix builds on the previous one by adding exactly one character at the end.
If two valid words have the same length, we pick the lexicographically smaller one. So between "apply" and "apple", we return "apple" because it comes first alphabetically.
This is a prefix-chain problem. A word of length k is buildable only if its prefix of length k-1 is also buildable. A word of length 1 is always buildable, since it is formed from the empty string by adding one character. This recursive structure points to two natural tools: sorting with a hash set, or a Trie.
words.length <= 1000 → The total number of words is small. Even O(n^2) approaches are feasible here.words[i].length <= 30 → Individual words are short. Operations on a single word (like extracting prefixes) are cheap.Take each word, extract every prefix of that word, and check whether all those prefixes exist in the dictionary. If they do, the word is buildable. We track the longest buildable word seen so far, breaking ties by lexicographic order.
Checking "are all prefixes present" is equivalent to checking buildability: if every prefix of "world" ("w", "wo", "wor", "worl") is in the dictionary, then the chain exists by definition. To make those lookups O(1), we put all words into a hash set first.
Input:
The set is {"w", "wo", "wor", "worl", "world"}. We process the words in array order:
"w": no prefixes to check (length 1), buildable. result = "w"."wo": prefix "w" is in the set, buildable. Length 2 beats 1, so result = "wo"."wor": prefixes "w", "wo" are in the set, buildable. result = "wor"."worl": prefixes "w", "wo", "wor" are in the set, buildable. result = "worl"."world": prefixes "w", "wo", "wor", "worl" are in the set, buildable. result = "world".No word is longer than "world", so the answer is "world".
Output:
The brute force re-checks the full prefix chain for every word. Processing words from shortest to longest removes that redundancy: once shorter words are known to be buildable, each word only needs to verify its immediate prefix.
If we sort the words first by length (shorter words first), then alphabetically within the same length, we can process words in order. By the time we encounter a word of length k, all words of length k-1 have already been processed.
A word is buildable if its prefix of length k-1 (the word minus its last character) is already in our set of buildable words. Words of length 1 are always buildable since they are built from the empty string by adding one character.
Sorting shortest-first, then alphabetically within a length, gives two guarantees. First, when we reach a word, its one-character-shorter prefix has already been processed, so if that prefix was buildable it is already in the set. Second, among words of equal length the alphabetically smallest is processed first, so the first buildable word at any length is the tie-break winner at that length.
Checking only the immediate prefix is sufficient because buildability is transitive. A word enters the set only when its immediate prefix is in the set, and that prefix entered only when its own prefix was in the set. So membership in the set already certifies the full chain back to the empty string, and re-verifying it is unnecessary.
The sorting approach spends O(n L log n) on the sort and creates a substring per word. A Trie stores shared prefixes once and lets us walk the prefix chains directly, dropping the sort and giving O(n * L) overall.
A Trie (prefix tree) maps the problem directly onto its structure, since every node in a Trie represents one prefix. We insert all words into a Trie, marking which nodes end a word, then search for the longest path from the root where every node along the way is a complete word.
If a node's prefix is itself a word in the dictionary (its isEnd flag is true), we can build up to that point. The answer is the deepest node reachable by following only edges into end-of-word nodes. A DFS from the root that explores children in alphabetical order and descends only into end-of-word nodes finds it: exploring a-z first means the deepest node it records is also the lexicographically smallest at that depth.