Prefix and Suffix Search - Complete Solution Guide
Prefix and Suffix Search is LeetCode problem 745, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Design a special dictionary that searches the words in it by a prefix and a suffix. Implement the WordFilter class: WordFilter(string[] words) Initializes the object with the words in the dictionary. f(string pref, string suff) Returns the index of the word in the dictionary, which has the prefix pref and the suffix suff . If there is more than one valid index, return the largest of them. If there is no such word in the dictionary, return -1 . Example 1: Input ["WordFilter", "f"] [[["apple"]], [
Detailed Explanation
The problem requires designing a `WordFilter` class that can efficiently search for words in a given dictionary based on both a prefix and a suffix. The `WordFilter` class has two methods: `__init__(words)` which initializes the dictionary with a list of words, and `f(pref, suff)` which returns the index of the word that has the given prefix `pref` and suffix `suff`. If multiple words satisfy the condition, the function should return the largest index. If no such word exists, it should return -1. The word lengths, prefix lengths, and suffix lengths are all limited to a maximum of 7 characters.
Solution Approach
The provided solutions use a Trie data structure to store all possible suffix + '#' + word combinations along with their indices. During initialization, the code iterates through each word and generates all possible suffixes. Each suffix is concatenated with '#', followed by the original word. These combined strings are then inserted into the Trie. Each Trie node stores the maximum index encountered so far for the given path. During the search (f) function, the provided suffix and prefix are combined (suffix + '#' + prefix) to form the search query. The code then traverses the Trie using the combined query. If the query exists in the Trie, the index stored at the end node (or during traversal) is returned. Otherwise, -1 is returned.
Step-by-Step Algorithm
- Step 1: Initialize a Trie data structure in the `__init__` method.
- Step 2: Iterate through the input `words` list with index `i`.
- Step 3: For each word, generate all possible suffixes by iterating from `j = 0` to `len(word)`.
- Step 4: Create a combined key: `suffix + '#' + word`.
- Step 5: Insert the combined key into the Trie. During insertion, store the index `i` of the word in each node along the path.
- Step 6: In the `f` method, combine the given `suff` and `pref` into a query string: `suff + '#' + pref`.
- Step 7: Traverse the Trie with the query string.
- Step 8: If any character in the query is not found in the Trie, return -1.
- Step 9: If the entire query is found, return the index stored at the last node of the Trie (or during traversal).
- Step 10: If the end of the traversal is reached but no index is present, or traversal was impossible, return -1.
Key Insights
- Insight 1: Pre-computing all possible prefix-suffix combinations is crucial for efficient searching. This avoids iterating through the entire word list for each query.
- Insight 2: Using a Trie data structure is an efficient way to store and search for strings based on prefixes. A modified Trie structure can be used to store combined suffix and prefix to achieve the prefix-suffix search requirement.
- Insight 3: The key to solving this problem efficiently lies in creating a combined search key. The combination of suffix + '#' + prefix allows us to use a single Trie for both prefix and suffix matching.
Complexity Analysis
Time Complexity: O(N*K^2)
Space Complexity: O(N*K^2)
Topics
This problem involves: Array, Hash Table, String, Design, Trie.
Companies
Asked at: Rubrik.