字典树可以用来解决搜索前缀问题
例如给若干个不同长度的字符串
找出有公共前缀的字符串有几个
面试遇到的

或者计算身份证号,同样前缀的身份证号有多少个
之前牛客模考遇到的

此算法在搜索引擎中非常使用,写了前几个字就会弹出来相关搜索。
以及在存储大量有重复前缀的数据时可以节省大量空间。
查找的时间复杂度就是O(字符串长度)

本质上是个树,因此用链表链接。以下代码用字符串来表示,假设只有26个小写字母。

package main

import "fmt"

//结构体根据需要自行设置
type tree struct {
	isWord bool
	//用来标记当前位置是否为一个单词
	count  int
	//用来标记当前位置的前缀出现次数
	next   [26]*tree
	//每个位置都有26个子树
}

func main() {
	//实现一个字典树
	word := []string{"abcdef", "aeqweq", "abcjer", "abcdgh", "abcdgk", "aberqer", "abeqwe", "a"}
	//随便设了个例子
	root := &tree{}
	//初始化一个根节点,从根节点开始查找
	nroot := root
	//节点要移动,因此留一个备用头节点,每次遍历完恢复到头部位置
	for _, w := range word {
	//取出一个单词
		root = nroot
		//将节点移到头部
		for i := range w {
		//判断单词的每一个字符
			if root.next[w[i]-'a'] == nil {
				//如果这个字符在的节点为nil,说明这个字符第一次出现,则要给它初始化
				root.next[w[i]-'a'] = &tree{}
			}
			//给这个字符出现次数加1
			root.next[w[i]-'a'].count++
			if i == len(w)-1 {
			//如果当前字符是该字母的最后一个字符了,就标记此前缀是一个单词
				root.next[w[i]-'a'].isWord = true
			}
			//移动到当前字符,重复下一个字符操作
			root = root.next[w[i]-'a']
		}
	}
	//初始化完成,下面是查询操作
	root = nroot
	//移动到头节点
	query := "abc"
	//设一个查询的前缀
	for i := range query {
	//如果遍历过程中 字符不存在就提前退出,输出不存在
		if root.next[query[i]-'a'] == nil {
			fmt.Println("not exist")
			break
		}
		//不然就移动到下一个字符
		root = root.next[query[i]-'a']
		//直到移动到了前缀的最后一个字符,就输出结果
		if i == len(query)-1 {
			fmt.Println("以", query, "开头的单词有", root.count, "个")
			fmt.Println(query, "is a word?", root.isWord)
		}
	}
}