Leetcode 745. Prefix and Suffix Search
发布日期:2025-04-05 00:15:46 浏览次数:14 分类:精选文章

本文共 2995 字,大约阅读时间需要 9 分钟。

为了有效解决问题,我们将使用前缀树和后缀树 结合技巧来实现快速查询。以下是详细的解决方法:


方法思路

为了高效找到具有给定前缀和后缀的单词,并且具有最大权重,我们可以使用前缀树和后缀树进行插入,然后针对每个查询分别处理。

  • 前缀树和后缀树的构建

    • 前缀树(tree):用于匹配单词的前缀,按常规顺序插入单词。
    • 后缀树(rtree):用于匹配单词的后缀,按照反向顺序插入单词。
  • 插入过程

    • 正向插入每个单词到前缀树。
    • 逆向插入每个单词到后缀树,以便后缀查询。
  • 查询过程

    • 使用前缀树查找所有以给定前缀开头的单词。
    • 使用后缀树查找所有以给定后缀结尾的单词。
    • 比较这两个集合,找出权重最大的单词。
  • 这种方法确保了插入和查询的效率,分别为O(n * m)和O(m),其中n是单词长度,m是查询时间复杂度。


    解决代码

    以下是实现用C++的代码:

    #include 
    #include
    #include
    using namespace std;struct TrieNode { vector
    last; TrieNode* next[26]; bool isEnd; TrieNode() : isEnd(false), last(0) { for (int i = 0; i < 26; ++i) { next[i] = NULL; } }};class TrieTree {public: TrieTree() { root = new TrieNode(); } void insert(const string& word, int index) { TrieNode* current = root; current->last.push_back(index); for (int i = 0; i < word.size(); ++i) { int c = word[i] - 'a'; if (current->next[c] == NULL) { current->next[c] = new TrieNode(); } current = current->next[c]; current->last.push_back(index); } current->isEnd = true; } void rinsert(const string& word, int index) { TrieNode* current = root; current->last.push_back(index); for (int i = word.size() - 1; i >= 0; --i) { int c = word[i] - 'a'; if (current->next[c] == NULL) { current->next[c] = new TrieNode(); } current = current->next[c]; current->last.push_back(index); } current->isEnd = true; } vector
    startWith(const string& prefix) { TrieNode* current = root; for (int i = 0; i < prefix.size(); ++i) { int c = prefix[i] - 'a'; if (current->next[c] == NULL) { return vector
    (); } current = current->next[c]; } return current->last; }private: TrieNode* root;};class WordFilter {public: WordFilter(vector
    words) { for (int i = 0; i < words.size(); ++i) { tree.insert(words[i], i); rtree.rinsert(words[i], i); } } int f(string prefix, string suffix) { vector
    pre = tree.startWith(prefix); if (pre.empty()) { return -1; } string reversedSuffix = string(suffix.rbegin(), suffix.rend()); vector
    suf = rtree.startWith(reversedSuffix); if (suf.empty()) { return -1; } int maxIndex = -1; int i = pre.size() - 1, j = suf.size() - 1; while (i >= 0 && j >= 0) { if (pre[i] == suf[j]) { if (pre[i] > maxIndex) { maxIndex = pre[i]; } --j; } else if (pre[i] < suf[j]) { --i; } else { break; } } return maxIndex != -1 ? maxIndex : -1; }private: TrieTree tree; TrieTree rtree;};

    代码解释

  • TrieNode:存储单词的终止节点信息,包括后继节点和单词权重的记录。
  • TrieTree:负责插入和前缀查询,使用正向和逆向插入构建前缀树和后缀树。
  • WordFilter:负责构建树结构并实现查询函数,返回满足条件的最大权重单词。
  • 该实现确保了插入和查询的效率,能够在大输入规模下高效运行。通过将每个单词的前缀和后缀分别存储在不同的树中,能够快速筛选出满足条件的单词,并因为每个树的查询复杂度为O(m),整体性能得到优化。

    上一篇:Leetcode 76 最小覆盖子串 java版
    下一篇:LeetCode 74 _ Search a 2D Matrix 在二维矩阵中寻找指定数字是否存在

    发表评论

    最新留言

    很好
    [***.229.124.182]2025年05月05日 23时24分40秒