字典树就是将一个个单词按照字母顺序建成树,可以用于单词去重、计算每种单词的出现次数、计算共出现多少种单词
本来用结构体存储的,但是后来做题的时候发现结构体内能开的节点大小确实有限,所以就去掉了结构体。
1 //关于引用说明:如果引用创建后,注意是否会修改x引用的对象,即x引用某值,再修改x的值。
2
3 #include<stdio.h>
4 #include<string.h>
5 const int maxm=5050; //maxm是所有单词的总长度
6
7 int Nxt[maxm][26]; //字母结点
8 int tail[maxm]; //记录某个结点是否为单词结尾,可以用bool型仅记录是否结尾,也可以int型记录其作为结尾的单词编号或记录单词出现过多少次
9 int Cnt[maxm]; //每个节点及后继所代表的单词数有多少,适用于字典树需要删除节点的时候使用
10 int size;
11
12 void init_trie(){ //初始化函数
13 memset(Nxt[0],0,sizeof(Nxt[0]));
14 memset(tail,0,sizeof(tail));
15 memset(Cnt,0,sizeof(Cnt));
16 size=1;
17 }
18
19 void insertword(char s[]){ //添加单词函数
20 int p=0;
21 for(int i=0;s[i];++i){
22 int &x=Nxt[p][s[i]-'a'];
23 if(!x){
24 memset(Nxt[size],0,sizeof(Nxt[size]));
25 x=size++;
26 }
27 Cnt[x]++; //用于记录后继单词数
28 p=x;
29 }
30 tail[p]++; //可以通过函数额外传一个单词编号的int型参数,此处即可将tail[p]赋为单词编号记录下来;也可以根据此处tail[p]的初始值是否为0,若为0可以用计数器加值记录共出现多少不同的单词;换成tail[p]++语句也可以用于记录某个单词出现过多少次
31 }
32
33 void deleteword(char s[]){
34 int p=0;
35 for(int i=0;s[i];++i){
36 int x=Nxt[p][s[i]-'a'];
37 Cnt[x]--;
38 p=x;
39 }
40 tail[p]--;
41 }
42
43 bool findword(char s[]){ //查询单词函数,也可以返回int型查询该单词出现过多少次
44 int p=0;
45 for(int i=0;s[i];++i){
46 int &x=Nxt[p][s[i]-'a'];
47 if(!x)return 0;
48 p=x;
49 }
50 return tail[p];
51 }
52
53 int main(){
54 char word[50];
55 int i;
56 init_trie();
57 // for(i=1;i<=10;i++){scanf("%s",word);insertword(word);}
58 // printf("\n");
59 // for(i=1;i<=20;i++){scanf("%s",word);printf("%d\n",findword(word));}
60 while(1){
61 int t;
62 scanf("%d%s",&t,word);
63 if(t==1)insertword(word);
64 if(t==2)deleteword(word);
65 if(t==3)printf("%d\n",findword(word));
66 }
67 return 0;
68 }