Loading docs/string/images/trie1.png 0 → 100644 +52.9 KiB Loading image diff... docs/string/trie.md +38 −6 Original line number Diff line number Diff line ## Trie 字典树,英文名 Trie。顾名思义,就是一个像字典一样的树。 先考虑怎么存多个串: ## 简介 一种树,每个结点有 $|∑|$ 个儿子,每条边表示一个字符。 先放一张图: 空间 $O(len)$ (如果假设 $|∑|$ 为常数)。  要判断某个串是否等于某个模式串,只要在 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 Loading Loading
docs/string/trie.md +38 −6 Original line number Diff line number Diff line ## Trie 字典树,英文名 Trie。顾名思义,就是一个像字典一样的树。 先考虑怎么存多个串: ## 简介 一种树,每个结点有 $|∑|$ 个儿子,每条边表示一个字符。 先放一张图: 空间 $O(len)$ (如果假设 $|∑|$ 为常数)。  要判断某个串是否等于某个模式串,只要在 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 Loading