字典树,顾名思义,就是把字典放到树上ui
不不不,是用字典来建树spa
把树建成字典的样子?指针
差很少。code
字典树指的是某个字符串集合对应的有根树,树的每条边上刚好对应一个字符,每一个顶点表明从根到该节点的路径所对应的字符串(将全部通过的边上的字符按照顺序链接起来)。有时咱们也称trie上的边为转移,节点为状态blog
是否是读起来很恶心?字符串
其实能够这么理解string
字典树就是一棵利用了字符串的公共前缀(好比gcakioi和gcakimo的前缀就是gcaki)来减小查询时间的树。当你查询单词的时候,只要沿着转移边查找就能够了,而且对于每一个单词的结尾,在字典树上都会有标记来表示这是一整个单词。io
举个例子class
如今有两个单词gc
A:GCAKIOI
B:GCAKIMO
那么这个字典树大概就是这个样子
很是直观对吧
就是在相同的时候合到一块儿,不一样的时候分开,在单词结尾进行标记就行了
操做实现:
1.初始化
一棵空的trie只包含一个根节点,该点的字符指针都指向空
int ch[N][Z]//Z为字符集大小,ch[i][j]表示节点i的j字符指向的节点 bool bo[N]//对给以i为终止字符的节点打标记
2.插入
当须要插入一个字符串S的时候,咱们令一个指针P指向根节点,而后依次扫描S中的每一个字符c
inline void build(string s,int id) { int now=1,len=s.size(); rep(i,0,len-1) { int c=s[i]-'a'; if(!ch[now][c]) { ch[now][c]=++cnt; }//若是尚未这个节点,就新建立一个节点 now=ch[now][c];//当前节点转移过去 } bo[now]=id;//给以节点now为终止节点的打上标记 }
3.查询
当咱们要查询一个字符串S在trie中是否出现时,咱们令一个指针P起初指向根节点,而后依次扫描S中的每个字符c
inline bool find(char s[]) { int now=1,len=strlen(s),c,k; rep(i,0,len-1)//在字典树上查找该单词 { c=s[i]-'a'; if(!ch[now][c]) return false; now=ch[now][c]; } return true; }
当字符均为小写字母或者大写字母时,trie能够当作一个26叉树
它的空间复杂度为O(N*C),N是节点个数,C是字符集的大小