Trie Tree 字典树

问题:统计词典中以给定字符串为前缀的单词数量

http://hihocoder.com/problemset/problem/1014

 

(1)数据结构
cnt:记录词典中所有单词经过该节点的次数
flag:标识是否构成以该节点结尾的单词
ptr:指向子节点的指针数组,假设字符集是小写英文字母,ptr[0]!=NULL隐式地表示该节点指向的下一节点对应字符'a'
根节点不包含字符,其余每个节点只包含一个字符

(2)插入单词
待插入的字符串word,指针p指向根节点,下标i指向word[0]
若字符串为空,不用处理;
否则,检查word[i]对应的指针p->ptr[word[i]-'a']是否为空;(记该指针为pNext)
若pNext为空,说明这个字符是第一次在树中出现,为该节点开辟一个新内存,并让pNext指向该新节点;
若pNext不为空,说明该字符在树中的节点已经建过了,令p = pNext即可;
把当前p所指的节点的cnt加1
重复以上过程,word中所有字符都处理完。
PS:最后,若p->cnt!=0,说明以p指向的节点字符是一个单词的尾部字符。可令p->flag=true。

对于长度为n的单词,插入单词的时间复杂度为O(n)。

(3)查询单词(查询前缀)
待查询单词prefix(若该prefix是一个完整单词,用布尔变量isWord标识它)
指针p指向根节点,下标i指向prefix[0]
若单词为空,不用处理;(以空串为前缀的单词数量为0)
否则,依次匹配每个prefix[i]
若p->ptr[prefix[i]-'a']为空,说明不存在以prefix为前缀的单词
若p->ptr[prefix[i]-'a']非空,继续i+1位置的下一次匹配,若直到匹配完prefix中所有字符,这个过程都没有断定匹配失败,也就是匹配成功,最终p指向树中节点的字符就是prefix的尾部字符。
PS:最后,若p->flag为true,说明prefix是一个完整单词。

对于长度为n的单词,查询单词的时间复杂度同样为O(n)。

 

(4)实现代码

 1 class Trie
 2 {
 3 private:
 4     int cnt;
 5     bool flag;
 6     Trie* ptr[26];
 7 public:
 8     Trie()
 9     {
10         cnt = 0, flag = false;
11         memset(ptr,0,sizeof(ptr)); //NULL
12     }
13 
14     void add(const string& word)
15     {
16         if(word == "") return;
17         Trie* p = this;
18         for(int i = 0; i < word.size(); ++i)
19         {
20             int c = word[i] - 'a';
21             if(p->ptr[c] == NULL)
22                 p->ptr[c] = new Trie;
23             p = p->ptr[c];
24             ++p->cnt;
25         }
26         p->flag = true;
27     }
28 
29     int query(const string& prefix, bool& isWord)
30     {
31         isWord = false;
32         if(prefix == "")return 0;
33         Trie* p = this;
34         for(int i = 0; i < prefix.size(); ++i)
35         {
36             int c = prefix[i] - 'a';
37             if(p->ptr[c] == NULL)
38                 return 0;
39             else
40                 p = p->ptr[c];
41         }
42 
43         if(p->flag) isWord = true;
44         return p->cnt;
45     }
46 
47 };

 

PS:对字典树进行先序遍历即可对单词进行字典序排序

posted @ 2017-10-15 21:29  junjie_x  阅读(229)  评论(0编辑  收藏  举报