{x}
blog image

Longest Word With All Prefixes

Solution Explanation: Longest Word With All Prefixes

This problem asks us to find the lexicographically smallest longest string from a given array words where all its prefixes are also present in words. The most efficient approach utilizes a Trie data structure.

Trie (Prefix Tree):

A Trie is a tree-like data structure specifically designed for efficient prefix-based searches. Each node in the Trie represents a character, and paths from the root to a leaf node represent words. The structure allows for quick checking of whether a word or prefix exists.

Algorithm:

  1. Trie Construction: We first construct a Trie from the input words. Each word is inserted into the Trie. The isEnd flag in each node indicates whether that node represents the end of a valid word.

  2. Longest Word Search: We iterate through the words array again. For each word:

    • We traverse the Trie to check if all prefixes of the current word exist. If a prefix is missing (indicated by isEnd being false at a node), we move on to the next word.
    • If all prefixes are found, we compare the current word with the longestWord found so far. We update longestWord if the current word is longer or if it's the same length but lexicographically smaller.

Time Complexity:

  • Trie construction: O(∑|w|), where the sum is over all words w in words. This is because inserting a word takes time proportional to its length.
  • Longest word search: O(∑|w|). Again, traversing a word in the Trie takes time proportional to its length.

Therefore, the overall time complexity is O(∑|w|), linear in the total number of characters in the input array.

Space Complexity:

The space complexity is dominated by the Trie. In the worst case, the Trie could store all prefixes of all words, leading to a space complexity of O(∑|w|).

Code Implementation (Python):

class TrieNode:
    def __init__(self):
        self.children = {}  # Dictionary to store children nodes (key: character, value: TrieNode)
        self.isEnd = False
 
class Solution:
    def longestWord(self, words: List[str]) -> str:
        root = TrieNode()
        for word in words:
            node = root
            for char in word:
                if char not in node.children:
                    node.children[char] = TrieNode()
                node = node.children[char]
            node.isEnd = True  # Mark the end of the word in the Trie
 
        longestWord = ""
        for word in words:
            isValid = True
            node = root
            for char in word:
                if char not in node.children or not node.children[char].isEnd:
                    isValid = False
                    break
                node = node.children[char]
            if isValid:
                if len(word) > len(longestWord) or (len(word) == len(longestWord) and word < longestWord):
                    longestWord = word
 
        return longestWord
 

The code in other languages (Java, C++, Go, TypeScript, Rust, C#) follows a similar structure, with the Trie implementation and search algorithm adapted to the specific language's features. The core idea remains the same: build a Trie, then efficiently search for the longest word with all prefixes present in the Trie.