这道题的核心思路是逆序字典树(Trie)——因为要找的是最长公共后缀,所以把字符串逆序插入 Trie,后缀就变成了前缀,问题就转化为经典的 Trie 前缀匹配问题。

题目思路

关键观察
- 后缀匹配 → 逆序后变成前缀匹配
- 每个 Trie 节点需要记录:当前路径下最短字符串的长度及其索引
- 如果多个字符串长度相同,取最早出现的索引

破平规则
1. 最长公共后缀优先
2. 后缀长度相同 → 字符串长度最短优先
3. 长度也相同 → 出现索引最早优先

Python3 实现

```python
class TrieNode:
    def __init__(self):
        self.children = {}  # 用字典更省空间
        self.min_len = float('inf')  # 当前路径下最短字符串长度
        self.idx = -1  # 当前路径下最短字符串的索引


class Solution:
    def stringIndices(self, wordsContainer: list[str], wordsQuery: list[str]) -> list[int]:
        root = TrieNode()
        
        # 更新节点信息:如果新字符串更短,或长度相同但索引更早
        def update(node: TrieNode, length: int, index: int) -> None:
            if length < node.min_len:
                node.min_len = length
                node.idx = index
        
        # 逆序插入字符串到 Trie
        def insert(word: str, index: int) -> None:
            length = len(word)
            node = root
            # 根节点也要更新(对应空后缀 "")
            update(node, length, index)
            
            # 逆序遍历,从最后一个字符开始
            for i in range(length - 1, -1, -1):
                c = word[i]
                if c not in node.children:
                    node.children[c] = TrieNode()
                node = node.children[c]
                update(node, length, index)
        
        # 查询最长公共后缀对应的索引
        def query(word: str) -> int:
            node = root
            # 逆序遍历查询字符串
            for i in range(len(word) - 1, -1, -1):
                c = word[i]
                if c not in node.children:
                    break
                node = node.children[c]
            return node.idx
        
        # 构建逆序 Trie
        for i, word in enumerate(wordsContainer):
            insert(word, i)
        
        # 处理每个查询
        return [query(word) for word in wordsQuery]
```

复杂度分析

指标    复杂度    
时间    O(Σ\|wordsContainer[i]\| + Σ\|wordsQuery[i]\|),即所有字符总数    
空间    O(Σ\|wordsContainer[i]\|),Trie 节点数(字典实现更省空间)    

关键点总结

1. 逆序插入:将后缀问题转化为前缀问题,这是 Trie 处理后缀的标准技巧
2. 节点信息维护:每个节点记录当前路径下最短字符串的长度和索引,保证查询时能直接返回最优解
3. 根节点处理:根节点对应空后缀 `""`,需要正确初始化(取所有字符串中最短的)
4. 破平顺序:通过 `length < node.min_len` 的条件判断,自然实现了"更短优先、更早优先"的破平规则
5. 字典 vs 数组:Python 中用 `dict` 代替固定大小的数组 `children[26]`,更省空间且更灵活

示例验证

输入:`wordsContainer = ["abcd","bcd","xbcd"]`, `wordsQuery = ["cd","bcd","xyz"]`

- 逆序插入:`"dcba"`、`"dcb"`、`"dcbx"`
- 查询 `"cd"`(逆序 `"dc"`):匹配到 `"dcb"` 的 `"dc"` 路径,返回索引 1
- 查询 `"bcd"`(逆序 `"dcb"`):完全匹配 `"dcb"`,返回索引 1
- 查询 `"xyz"`(逆序 `"zyx"`):无匹配,返回根节点的最短字符串索引 1

输出:`[1, 1, 1]`

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐