Statement▼
You are given two arrays of strings, wordsContainer and wordsQuery.
For each string wordsQuery[i], find the string in wordsContainer that shares the longest common suffix with it.
If multiple strings in
wordsContainershare the same longest suffix, choose the one with the smallest length.If two or more such strings have the same smallest length, choose the string that appears earliest in
wordsContainer.
Return an array of integers ans, where ans[i] is the index of the chosen string in wordsContainer for the query wordsQuery[i].
Constraints:
1≤ wordsContainer.length, wordsQuery.length≤104 1≤ wordsContainer[i].length≤5∗103 1≤ wordsQuery[i].length≤5∗103 wordsContainer[i]consists only of lowercase English letters.wordsQuery[i]consists only of lowercase English letters.Sum of
wordsContainer[i].lengthis, at most5∗105 .Sum of
wordsQuery[i].lengthis, at most5∗105 .
Solution
To solve the problem, build a reversed trie from wordsContainer, where each node represents a character from the end of a word toward its start. We insert each word back-to-front so that suffix matching becomes prefix matching. Store the best candidate at every node as a pair (index, length), where “best” means smallest length, and if lengths tie, the earliest index in wordsContainer. For each word in wordsContainer, start from the root, update the stored best candidate if the current word is smaller (or first in order for ties), and then insert its characters in reverse, updating the best candidate at every step. Once the trie is built, the algorithm processes each word in wordsQuery by traversing the trie in reverse character order, stopping if a character path does not exist. The best candidate index stored at the last visited node is then appended to the result list.
The steps of the algorithm are as follows:
Create an empty dictionary
trieto serve as the root node. Each node maps characters to child nodes and uses the special keyNoneto store the best candidate as(index, length).Build the reversed trie from
wordsContainer:
For each(index, word)inwordsContainer:Set
currentNode = trie.At the root, set
currentNode[None]to(index, len(word))if it’s unset or iflen(word) < currentNode[None][1](i.e., the current word has the smallest length so far). If lengths are equal, retain the existing pair so the earlier index remains.Iterate through the characters of the
wordin reverse:Create the child node for
charif absent, then movecurrentNodeto that child.At each node, update the stored best candidate using the same rule (prefer smallest length; on equal length, retain the already stored candidate (corresponding to the earliest index seen on this path).
Query the trie using
wordsQuery:
Initializeresult = []. For eachqueryWordinwordsQuery:Set
currentNode = trie.Traverse the trie using the characters of
queryWordin reverse, stopping if a requiredcharis not present.After the traversal, append
currentNode[None][0](the stored best candidate’s index) toresult.
Return
result, the list of indices inwordsContainercorresponding to the smallest words among those sharing the longest common suffix with eachqueryWord.
Let’s look at the following illustration to get a better understanding of the solution: