Unverified Commit e3eeaf6d authored by ir1d's avatar ir1d Committed by GitHub
Browse files

update: 字典树:添加字典树图片、代码 (#1341)

update: 字典树:添加字典树图片、代码
parents f9be92f3 e1e6d763
Loading
Loading
Loading
Loading
+52.9 KiB
Loading image diff...
+38 −6
Original line number Diff line number Diff line
## Trie
字典树,英文名 Trie。顾名思义,就是一个像字典一样的树。

先考虑怎么存多个串:
## 简介

一种树,每个结点有 $|∑|$ 个儿子,每条边表示一个字符。
先放一张图:

空间 $O(len)$ (如果假设 $|∑|$ 为常数)。
![trie1](./images/trie1.png)

要判断某个串是否等于某个模式串,只要在 Trie 上走一遍(线性的)。
可以发现,这棵字典树用边来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。举个例子,$1\to4\to 8\to 12$ 表示的就是字符串 `caa`


Trie 的结构非常好懂,我们用一个二维数组 $tr[i,j]$ 表示结点 i 的 j 字符指向的下一个结点,或着说是结点 i 代表的字符串后面添加一个字符 j 形成的字符串的结点。(j 的取值和字符集大小有关,不一定是 $0\sim 26$)

## 代码实现

放一个结构体封装的模板,十分好懂

```cpp
struct trie{
    int nex[100000][26],cnt;
	bool exist[100000];// 该结点结尾的字符串是否存在

	void insert(char *s,int l){// 插入字符串
		int p=0;
		for(int i=0;i<l;i++){
            int c=s[i]-'a';
			if(!nex[p][c])nex[p][c]=++cnt;// 如果没有,就添加结点
			p=nex[p][c];
		}
		exist[p]=1;
	}
	bool find(char *s,int l){// 查找字符串
		int p=0;
		for(int i=0;i<l;i++){int c=s[i]-'a';
			if(!nex[p][c])return 0;
			p=nex[p][c];
		}
		return exist[p];
	}
};
```

## 在 Trie 上 KMP