正文
前缀树(Trie),又称字典树,是一种多叉树结构。它通过利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。
算法模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class TrieNode { val children = arrayOfNulls<TrieNode>(26) var isEndOfWord = false }
class Trie { private val root = TrieNode()
fun insert(word: String) { var node = root for (char in word) { val index = char - 'a' if (node.children[index] == null) { node.children[index] = TrieNode() } node = node.children[index]!! } node.isEndOfWord = true }
fun search(word: String): Boolean { var node = findNode(word) return node != null && node.isEndOfWord }
fun startsWith(prefix: String): Boolean { return findNode(prefix) != null }
private fun findNode(prefix: String): TrieNode? { var node = root for (char in prefix) { val index = char - 'a' if (node.children[index] == null) { return null } node = node.children[index]!! } return node } }
|
使用说明
核心特性:
- 高效前缀匹配:查找前缀或单词的时间复杂度仅与单词长度 $L$ 相关,即 $O(L)$。
- 空间换时间:利用数组或哈希表存储子节点,虽然空间占用较大,但查询极快。
适用场景:
- 单词搜索:如“搜索提示”、“拼写检查”。
- 字符串排序:字典树遍历本身就是一种排序。
- 统计词频:可以在
TrieNode 中加入 count 字段。
核心技巧:
children 数组:如果字符集固定(如 26 个字母),使用数组速度最快;如果不固定,可改用 HashMap。
- **
isEndOfWord**:必须在插入单词的最后一个字符节点处设为 true。
注意点:
- 注意处理空字符串的特殊情况。
- 如果需要支持删除操作,通常采用引用计数或在
isEndOfWord 置为 false 后递归删除无用节点。