PS:本人蒟蒻,欢迎大家指正错误

一,字典树(Trie-Tree)

定义:又名单词查找树,为树状结构,是哈希树的变种。利用字符串的公共前缀,在存储时节约空间,查询时节约时间,尽可能减少不必要的字符比较。

二,功能

1.      利用公共前缀存储大量字符串

2.      减少查找字符串时的比较

3.      查询一个字串s在字典中总共出现的次数

三,代码实现

 

利用字符与a的相对距离保存到整棵树中,a~z对应着0-25.

1.      字典树节点

1 //const int maxn=26;
2 struct TrieNode{
3     int num;//共有多少个字符串经过该节点,即从根节点到该节点组成的字串出现次数
4     bool isEnd;//判断是否是一个字符串的结尾
5     struct TrieNode *son[maxn];//指向26棵子树
6 };

2.      建树函数

1 TrieNode *Build(){
2     TrieNode *Head=new TrieNode;//创建头节点
3     Head->isEnd=false;            //当前字典中没有字符串
4     Head->num=0;                // 
5     for(int i=0; i<maxn; i++){
6         Head->son[i]=NULL;//将26个儿子均置为空
7     }
8     return Head;                    //返回根节点
9 }

3.      添加字符串函数

 1 TrieNode *Update(TrieNode *head, string s){
 2     TrieNode *t=head;
 3     int k=0;
 4     while(t->son[s[k]-'a']!=NULL&& k<s.size()){//根据公共前缀向下查找
 5         t->num++;
 6         t=t->son[s[k]-'a'];
 7         k++;
 8     }
 9     if(k==s.size()){    //说明新添加的字符串是字典中某串前缀的子串,添加结束标记
10         t->isEnd=true;
11     }else{
12         while(k<s.size()){        //根据字符串添加新的节点
13             TrieNode *current=new TrieNode;
14             current->num=1;
15             current->isEnd=false;
16             for(int i=0; i<maxn; i++){    //其他方向均置为空
17                 current->son[i]=NULL;
18             }
19             t->son[s[k]-'a']=current;    
20             t=t->son[s[k]-'a'];
21             k++;
22         }
23         t->isEnd=true;            //添加结束标记
24     }
25     return head;        //返回根节点
26 }

4.      查找函数

 1 bool Search(TrieNode *head, string s){
 2     TrieNode *current=head;
 3     int k=0;
 4     while(k<s.size()&&current->son[s[k]-'a']!=NULL){//根据查找字符串向叶节点延申
 5         current=current->son[s[k]-'a'];
 6         k++;
 7     }
 8     if(k<s.size())        //说明该方向查找到叶节点而字符串未匹配完毕,说明没有
 9         return false;
10     return current->isEnd;//字符串匹配完毕,返回结束标记
11 }

5.  公共前缀计数函数

 1 int Counter(TrieNode *head, string str){
 2     TrieNode *current=head;
 3     int k=0;
 4     while(k<str.size()&&current->son[str[k]-'a']!=NULL){//根据字符串向叶节点搜索
 5         current=current->son[str[k]-'a'];
 6         k++;
 7     }
 8     if(k<str.size())
 9         return -1;    //意外结束
10     else
11         return current->num;//返回当前公共前缀的数量
12 }

6.  打印字典树(通过递归实现字典序打印)

 1 void Output(TrieNode *head, string print){
 2     if(head->isEnd){            //已经形成一个单词,打印出来
 3         cout<<print<<endl;
 4     }
 5     for(int i=0; i<maxn; i++){        //遍历26个方向
 6         if(head->son[i]!=NULL){
 7             print+=('a'+i);
 8             Output(head->son[i], print);//递归调用打印函数
 9             print.erase(print.end()-1, print.end());
10         }
11     }
12 }

代码整合:

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=26;
  6 struct TrieNode{
  7     int num;
  8     bool isEnd;
  9     struct TrieNode *son[maxn];
 10 };
 11 
 12 TrieNode *Build(){
 13     TrieNode *Head=new TrieNode;
 14     Head->isEnd=false;
 15     Head->num=1;
 16     for(int i=0; i<maxn; i++){
 17         Head->son[i]=NULL;
 18     }
 19     return Head;
 20 }
 21 
 22 TrieNode *Update(TrieNode *head, string s){
 23     TrieNode *t=head;
 24     int k=0;
 25     while(t->son[s[k]-'a']!=NULL&& k<s.size()){
 26         t=t->son[s[k]-'a'];
 27         t->num++;
 28         k++;
 29     }
 30     if(k==s.size()){
 31         t->isEnd=true;
 32     }else{
 33         while(k<s.size()){
 34             TrieNode *current=new TrieNode;
 35             current->num=1;
 36             current->isEnd=false;
 37             for(int i=0; i<maxn; i++){
 38                 current->son[i]=NULL;
 39             }
 40             t->son[s[k]-'a']=current;
 41             t=t->son[s[k]-'a'];
 42             k++;
 43         }
 44         t->isEnd=true;
 45     }
 46     return head;
 47 }
 48 
 49 bool Search(TrieNode *head, string s){
 50     TrieNode *current=head;
 51     int k=0;
 52     while(k<s.size()&&current->son[s[k]-'a']!=NULL){
 53         current=current->son[s[k]-'a'];
 54         k++;
 55     }
 56     if(k<s.size())
 57         return false;
 58     return current->isEnd;
 59 }
 60 /*
 61 TrieNode *Erase(TrieNode *head, string s){
 62     TrieNode *current=head, *pre=head;
 63     int k=0, n;
 64     while(1){
 65         current=current->son[s[k]-'a'];
 66         k++;
 67         if(k>=s.size())
 68             break;
 69         if(current->isEnd=true){
 70             n=k;
 71             pre=current;
 72         }
 73     }
 74     bool flag=false;
 75     for(int i=0; i<maxn; i++){
 76         if(current->son[i]!=NULL)
 77             flag=true;
 78     }
 79     if(flag)
 80         current->isEnd=false;
 81     else{
 82         n++;
 83         current=pre->son[s[n]-'a'];
 84         while(n<s.size()){
 85             TrieNode *tmp=current;
 86             n++;
 87             current=current->son[s[n]-'a'];
 88             delete tmp;
 89         }
 90     }
 91     return head;
 92 }
 93 */
 94 
 95 int Counter(TrieNode *head, string str){
 96     TrieNode *current=head;
 97     int k=0;
 98     while(k<str.size()&&current->son[str[k]-'a']!=NULL){
 99         current=current->son[str[k]-'a'];
100         k++;
101     }
102     if(k<str.size())
103         return -1;
104     else
105         return current->num;
106 }
107 
108 void Output(TrieNode *head, string print){
109     if(head->isEnd){
110         cout<<print<<endl;
111     }
112     for(int i=0; i<maxn; i++){
113         if(head->son[i]!=NULL){
114             print+=('a'+i);
115             Output(head->son[i], print);
116             print.erase(print.end()-1, print.end());
117         }
118     }
119 }
120 
121 int main(){
122     TrieNode *Head=Build();
123     int n;
124     cin>>n;
125     string str;
126     for(int i=0; i<n; i++){
127         cin>>str;
128         Head=Update(Head, str);
129     }
130     cin>>str;
131     if(Search(Head, str)){
132         cout<<"Yes"<<endl;
133         //Head=Erase(Head, str);
134     }
135     else
136         cout<<"No"<<endl;
137     cout<<Counter(Head, str)<<endl;
138     string print;
139     Output(Head, print);
140     return 0;
141 }

 

posted on 2019-01-23 16:52  Scotton  阅读(204)  评论(0编辑  收藏  举报