单词超集判定算法选型:基于Trie的DFS是否为最优方案?
拼词拓展单词的最优解法探讨
你需要实现的功能是找出**所有包含输入单词全部字母(每个字母至少出现一次,顺序无关)**的单词,比如输入HIS,要筛选出SHIV、HIVES这类包含H、I、S各至少一次的单词。
你的DFS+Trie方案分析
你提出的基于Trie的深度优先搜索方案是可行的,但并非最优解,核心问题在于:
- 遍历整个Trie会产生大量无效分支:英语词库中存在大量短单词或字母组成不匹配的单词,很多Trie分支从一开始就无法满足输入单词的字母要求,做了很多无用功。
- 递归过程中对多集合(MultiSet)的修改/回溯操作,在输入单词较长时会带来额外的性能开销。
成熟的最优解法:字母计数签名匹配
这类问题更高效的标准解法是预计算单词的字母频率签名,通过签名匹配快速筛选结果,具体步骤如下:
1. 预处理阶段
- 对词库中的每个单词,生成对应的字母计数数组:比如用长度为26的数组,每个位置对应a-z的出现次数(例如
HIS的计数数组中,H对应位置为1,I对应位置为1,S对应位置为1,其余为0)。 - 可以将计数数组转换为可哈希的结构(比如拼接成字符串
H:1,I:1,S:1),或者直接保留数组形式,同时将词库按单词长度分组存储(比如长度3的单词放一组,长度4的放另一组)。
2. 查询阶段
- 计算输入单词的字母计数数组
target_counts。 - 只遍历词库中长度≥输入单词长度的分组,对每个单词的计数数组
word_counts进行检查:对于每个字母c,word_counts[c] ≥ target_counts[c]。如果满足条件,就将该单词加入结果列表。
优化点
- 按长度分组后,查询时可以直接跳过所有短于输入单词的分组,大幅减少遍历范围。
- 若追求极致性能,可将字母计数编码为大整数(比如每个字母用4位存储计数,26个字母共104位,用支持大整数的语言存储),通过位运算快速判断计数是否满足要求。
两种方案对比
- 字母计数签名方案的查询时间复杂度为O(N*26)(N为符合长度要求的单词数),远低于Trie-DFS方案最坏情况下的O(M)(M为Trie节点总数),在大词库场景下优势明显。
- 字母计数方案的实现逻辑更简单,不需要维护复杂的Trie结构,代码量更少,调试成本更低。
总结
你的Trie-DFS方案可行但效率不足,成熟的最优解法是基于字母计数签名的预计算与匹配,既满足需求又能保证查询效率。
内容的提问来源于stack exchange,提问作者ADC2000
相关产品推荐
相关产品推荐

