前缀树
是关于“字典”的一棵树。即:它是对于字典的一种存储方式。
这个词典中的每个“单词”就是从根节点出发一直到某一个目标节点的路径,路径中每条边的字母连起来就是一个单词。
上图到橙色节点(目标节点)所组成的单词分别为:
a、abc、bac、bbc、ca
功能:
- 维护字符串集合(即字典)
- 向字符串集合中插入字符串(即建树)
- 查询字符串集合中是否有某个字符串
- 统计字符串在集合中出现的个数
- 将字符串集合按字典序排序
- 求集合内两个字符串的LCP(Longest Common Prefix 最长公共前缀)
结点结构体定义:
#define MAXSIZE 26
struct node {
bool flag; //若结点是单词的结尾,值为 true,否则为 falseint next[MAXSIZE]; //指向后继的游标数组
}trie[1000001];
插入
void Insert(string str, int &space)
{
int order;int idx = 1; //从第一层向下挖掘for (int i = 0; i < str.length(); i++){
order = str[i] - 'a'; //将字符转换为其在字母表的顺序if (trie[idx].next[order] == 0) //若 idx 没有该字符的子结点{
trie[idx].next[order] = space++; //启用第 space 号结点,拷贝新结点的编号idx = trie[idx].next[order]; //idx 结点的对应字母的后继为 spacetrie[idx].flag = false; //标记新结点不是单词的结尾}elseidx = trie[idx].next[order]; //前缀已存在,继续挖掘}trie[idx].flag = true; //flag 成员设置为 true,表示单词结尾
}
查找
bool Find(string str)
{
int order;int idx = 1; //从第一层向下挖掘for (int i = 0; i < str.length(); i++){
order = str[i] - 'a'; //将字符转换为其在字母表的顺序if (trie[idx].next[order] == 0) //若字母失配,匹配结束{
return false;}idx = trie[idx].next[order]; //存在对应字母,匹配继续}if (trie[idx].flag == false) //若成功匹配,但是不为单词结尾return false;elsereturn true; //单词匹配成功,返回 true
}