Statement▼
You are given an array of strings, words. Your task is to find the longest string in words such that every prefix of this string is also present in words.
A prefix of a string is any leading substring. For example, the prefixes of "apple" are "a", "ap", "app", and "appl".
If multiple valid strings have the same maximum length, return the lexicographically smallest one.
If no such string exists, return an empty string
"".
Constraints:
1≤ words.length≤103 1≤ words[i].length≤103 1≤ sum(words[i].length)≤103 words[i]consists only of lowercase English letters.
Solution
A trie (prefix tree) is a tree-based data structure that efficiently stores strings by sharing common prefixes. Each node in the trie represents a character, and the path from the root to any node corresponds to a word’s prefix.
This property makes tries especially useful for problems involving prefix relationships. In this problem, we use the trie to determine whether a word can be built one character at a time from other words in the list. Each word is inserted into the trie, and the end of every complete word is marked. Later, to validate any given word, we traverse it in the trie and confirm that each of its prefixes is also marked as a complete word. This structure enables efficient lookups and eliminates the need for repeated prefix searches through the original array.
The key idea is simple: A word is valid if, while traversing it in the trie, every node along its path represents a complete word.
Using this principle, the algorithm determines the longest word that can be built step by step from other words in the list. After inserting all words into the trie, each word is validated by ensuring that every prefix node corresponds to a complete word (is_end = True). Only those words meeting this condition are considered valid.
Among all valid words, the algorithm continuously tracks the longest one. If multiple words share the same length, it selects the lexicographically smallest (dictionary order) word. This ensures that the final result is the longest and lexicographically smallest word that can be formed by successively adding characters from existing words.
The steps of the algorithm are as follows:
Define a
TrieNodeclass where each node represents a single character in a word. Each node contains:children: A dictionary mapping characters to their corresponding child nodes.is_end: A boolean flag (initialized asFalse) that indicates whether the current node marks the end of a complete word.
Initialize a
Trieobject with a root node. For every word in the input list:Start from the root node.
For each character
chin the word:If
chis absent in the current node’schildren, create a newTrieNode.Move to the child node corresponding to
ch.
After inserting the final character, mark the node’s
is_end = True.
Define a method,
is_valid_word(word), to determine whether a word can be formed by successively adding one character at a time from other valid words.Start from the root node and traverse each character in the word.
Move to the corresponding child node for every character and check whether
is_endisTrue.If any node’s
is_endisFalse, it means that a prefix of the word is not a complete word, returnFalse.Return
TrueIf all prefixes are valid (i.e., all nodes encountered haveis_end = True).
Initialize an empty string,
ans, to store the best result found so far. Iterate through all words in the list:If
is_valid_word(word)returnsTrue:If
len(word) > len(ans), updateans = word.If
len(word) == len(ans)andword < ans, updateans = wordto ensure lexicographical order.
After checking all words, return
ansas the longest valid word that can be built one character at a time from other words in the list.
Let’s look at the following illustration to get a better understanding of the solution: