
Leetcode 745. Prefix and Suffix Search
TrieNode:存储单词的终止节点信息,包括后继节点和单词权重的记录。 TrieTree:负责插入和前缀查询,使用正向和逆向插入构建前缀树和后缀树。 WordFilter:负责构建树结构并实现查询函数,返回满足条件的最大权重单词。
发布日期: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;};
代码解释
该实现确保了插入和查询的效率,能够在大输入规模下高效运行。通过将每个单词的前缀和后缀分别存储在不同的树中,能够快速筛选出满足条件的单词,并因为每个树的查询复杂度为O(m),整体性能得到优化。
发表评论
最新留言
很好
[***.229.124.182]2025年05月05日 23时24分40秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
libtorch中python中cuda可以使用,但是是c++环境中不行
2025-04-05
LibTorch中TensorOptions的使用
2025-04-05
LibTorch之DataSet数据集处理方法
2025-04-05
LibTorch之优化器
2025-04-05
LibTorch之全连接层(torch::nn::Linear)使用
2025-04-05
LibTorch之图像分类
2025-04-05
LibTorch之张量操作与线性回归
2025-04-05
LibTorch之损失函数
2025-04-05
LibTorch之激活函数层
2025-04-05
LibTorch之网络层中的卷积层
2025-04-05
LibTorch之网络模型构建
2025-04-05
Libtorch在vs中c++相关配置
2025-04-05
LibTorch实现LeNet
2025-04-05
LibTorch实现MLP(多层感知机)
2025-04-05
Libtorch常用代码
2025-04-05
LibTorch框架学习
2025-04-05
libtorch组成讲解之ATen、c10、at、csrc
2025-04-05
libvirt TLS
2025-04-05
libvirtd tcp 方式远程连接配置步骤
2025-04-05
libvirt报错处理及解决
2025-04-05