100268. 最长公共后缀查询

2024/03/24 leetcode 共 3112 字,约 9 分钟

title

problem link

相关企业

提示

给你两个字符串数组 wordsContainer 和 wordsQuery 。

对于每个 wordsQuery[i] ,你需要从 wordsContainer 中找到一个与 wordsQuery[i] 有 最长公共后缀 的字符串。如果 wordsContainer 中有两个或者更多字符串有最长公共后缀,那么答案为长度 最短 的。如果有超过两个字符串有 相同 最短长度,那么答案为它们在 wordsContainer 中出现 更早 的一个。

请你返回一个整数数组 ans ,其中 ans[i]是 wordsContainer中与 wordsQuery[i] 有 最长公共后缀 字符串的下标。

示例 1:

输入:wordsContainer = [“abcd”,”bcd”,”xbcd”], wordsQuery = [“cd”,”bcd”,”xyz”]

输出:[1,1,1]

解释:

我们分别来看每一个 wordsQuery[i] :

  • 对于 wordsQuery[0] = "cd" ,wordsContainer 中有最长公共后缀 "cd" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
  • 对于 wordsQuery[1] = "bcd" ,wordsContainer 中有最长公共后缀 "bcd" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。
  • 对于 wordsQuery[2] = "xyz" ,wordsContainer 中没有字符串跟它有公共后缀,所以最长公共后缀为 "" ,下标为 0 ,1 和 2 的字符串都得到这一公共后缀。这些字符串中, 答案是下标为 1 的字符串,因为它的长度为 3 ,是最短的字符串。

示例 2:

输入:wordsContainer = [“abcdefgh”,”poiuygh”,”ghghgh”], wordsQuery = [“gh”,”acbfgh”,”acbfegh”]

输出:[2,0,2]

解释:

我们分别来看每一个 wordsQuery[i] :

  • 对于 wordsQuery[0] = "gh" ,wordsContainer 中有最长公共后缀 "gh" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 2 的字符串,因为它的长度为 6 ,是最短的字符串。
  • 对于 wordsQuery[1] = "acbfgh" ,只有下标为 0 的字符串有最长公共后缀 "fgh" 。所以尽管下标为 2 的字符串是最短的字符串,但答案是 0 。
  • 对于 wordsQuery[2] = "acbfegh" ,wordsContainer 中有最长公共后缀 "gh" 的字符串下标分别为 0 ,1 和 2 。这些字符串中,答案是下标为 2 的字符串,因为它的长度为 6 ,是最短的字符串。

提示:

  • 1 <= wordsContainer.length, wordsQuery.length <= 104
  • 1 <= wordsContainer[i].length <= 5 * 103
  • 1 <= wordsQuery[i].length <= 5 * 103
  • wordsContainer[i] 只包含小写英文字母。
  • wordsQuery[i] 只包含小写英文字母。
  • wordsContainer[i].length 的和至多为 5 * 105 。
  • wordsQuery[i].length 的和至多为 5 * 105 。

solution

字典树题目,字典树节点上额外维护最小长度的string index,这样search这个Trie树时可以直接返回这个index。



class TrieNode:
    def __init__(self):
        self.precount = 0
        self.count = 0
        self.children = {}
        self.min_l = float('inf')
        self.index = 0


class Trie:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root = TrieNode()

    def insert(self, word: str) -> None:
        """
        Inserts a word into the trie.
        """
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
            node.precount += 1
        node.count += 1

    def insert2(self, word: str, i, l) -> None:
        """
        Inserts a word into the trie.
        记录下word的index以及当前子树最小的index
        """
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            if node.min_l > l:
                node.min_l = l
                node.index = i
            node = node.children[c]
            node.precount += 1
        if node.min_l > l:
            node.min_l = l
            node.index = i
        node.count += 1

    def search(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        node = self.root
        for c in word:
            if c not in node.children:
                return False
            node = node.children[c]
        return node.count > 0

    def search2(self, word: str) -> int:
        """
        找最长公共前缀的对应字符串index
        """
        node = self.root
        for c in word:
            if c not in node.children:
                return node.index
            node = node.children[c]
        return node.index

    def searchPrefix(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        node = self.root
        for i, c in enumerate(word):
            if c not in node.children:
                return word[:i]
            node = node.children[c]
        return word

    def startsWith(self, prefix: str) -> bool:
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        node = self.root
        for c in prefix:
            if c not in node.children:
                return False
            node = node.children[c]
        return node.precount > 0

class Solution:
    def stringIndices(self, wordsContainer: List[str], wordsQuery: List[str]) -> List[int]:
        a = [w[::-1] for w in wordsContainer]
        b = [w[::-1] for w in wordsQuery]
        # print(a, b)
        trie = Trie()
        for i, w in enumerate(a):
            trie.insert2(w, i, len(w))
        ans = []
        for w in b:
            r = trie.search2(w)
            ans.append(r)
        return ans

Search

    Table of Contents