Skip to content

Commit

Permalink
trie
Browse files Browse the repository at this point in the history
  • Loading branch information
yk committed Feb 13, 2024
1 parent 8a1fcdc commit a4187c7
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ auto = false
# 是否显示代码块的复制按钮
copy = true
# 默认展开显示的代码行数
maxShownLines = 50
maxShownLines = 100
# 表格配置
# [params.page.table]
# # 是否开启表格排序
Expand Down
103 changes: 103 additions & 0 deletions content/posts/2024/02/0213.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
title: '0203-前缀树'
date: 2024-02-13T17:54:23+08:00
lastmod:
tags: []
series: []
categories: []
---

## 概念

前缀树,也叫字典树,就是一种数据结构,比如有一组字符串 `['abc', 'ab', 'bc', 'bck']`,那么它的前缀树是这样的:

<img src='https://cdn.jsdelivr.net/gh/yokiizx/picgo@main/img/202402131753139.png' width='200px'/>

核心:**字符在树的树枝上,节点上保存着信息**

- p:通过下接树枝字符的字符串数量. -- 可以查询前缀数量
- e:以上接树枝字符结尾的字符串数量. -- 可以查询字符串

对应的数据结构如下:

```js
// ### 实现前缀树 lc.208
class TrieNode {
constructor(pass = 0, end = 0) {
// this.isEnd = false // 这个是另一种实现方式,leetcode 208 题题解,下面这种能多做一种统计
this.pass = pass // 通过下接树枝字符的字符串数量
this.end = end // 以上接树枝字符结尾的字符串数量
this.next = {} // {char: TrieNode} 的 map 集, 字符有限,有些教程也用数组实现
}
}
class Trie {
constructor() {
this.root = new TrieNode()
}
insert(str) {
if (!str) return
const chars = str.split('')
let node = this.root
for (const s of chars) {
if (!node.next[s]) {
node.next[s] = new TrieNode()
}
node = node.next[s]
node.pass++
}
node.end++
}
search(str) {
if (!str) return 0 // 根据实际问题看返回 0 还是 false 值
const chars = str.split('')
let node = this.root
for (const s of chars) {
if (node.next[s]) {
node = node.next[s]
} else {
return 0 // 根据实际问题看返回 0 还是 false 值
}
}
return node.end // 根据实际问题 看是返回 end, 还是 返回 true 值
}
// 有几个以 str 为前缀的字符串。根据实际问题,看是返回 Boolean 还是 number
startWidth(str) {
const chars = str.split('')
let node = this.root
for (const s of chars) {
if (node.next[s]) {
node = node.next[s]
} else {
return 0
}
}
return node.pass
}
delete(str) {
if (this.search(str) !== 0) {
const chars = str.split('')
let node = this.root
node.pass--
for (const s of chars) {
node.next[s].pass--
if (node.next[s].pass == 0) {
node.next[s] = null // 有一个节点的 pass 为 0 的时候,说明后面就都没得了,可以直接把后续置 null 了
return
}
node = node.next[s]
}
node.end--
}
}
}
```

---

前缀树的作用:

1. 查询字符串
2. 查询以某个字符串为前缀的字符串有多少个
3. 自动补完

上面两个作用,第一个 hashMap 也能做到,但是其他点,则是前缀树发挥其本领的绝对领地了。

0 comments on commit a4187c7

Please sign in to comment.