3道入门字典树例题,以及模板【HDU1251/HDU1305/HDU1671】

HDU1251:http://acm.hdu.edu.cn/showproblem.php?pid=1251

题目大意:求得以该字符串为前缀的数目,注意输入格式就行了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 char str[20];
 5 int trie[100000 * 4][30], cnt;
 6 int sum[100000 * 4];
 7 
 8 void insert()
 9 {
10     int len = strlen(str);
11     int rt = 0;
12     for(int i = 0; i < len; i ++)
13     {
14         int id = str[i] - 'a';
15         if(!trie[rt][id])
16             trie[rt][id] = ++ cnt;
17         rt = trie[rt][id];
18         sum[rt] ++;
19     }
20 }
21 
22 int serach()
23 {
24     int len = strlen(str);
25     int rt = 0;
26     for(int i = 0; i < len; i ++)
27     {
28         int id = str[i] - 'a';
29         if(!trie[rt][id])
30             return 0;
31         rt = trie[rt][id];
32     }
33     return sum[rt];
34 }
35 
36 int main()
37 {
38     while(gets(str))
39     {
40         if(strlen(str) == 0)
41             break;
42         insert();
43     }
44     while(scanf("%s", str) != EOF)
45     {
46         printf("%d\n", serach());
47     }
48     return 0;
49 }
HDU1251

HDU1305:http://acm.hdu.edu.cn/showproblem.php?pid=1305

题目大意:字符串之间互相不为前缀,则输出YES 否则NO

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define mem(a, b) memset(a, b, sizeof(a))
 4 
 5 int trie[40000][3], tot, k_rt[40000], cnt, sum[40000];
 6 char str[15];
 7 
 8 void insert()
 9 {
10     int len = strlen(str);
11     int root = 0;
12     for(int i = 0; i < len; i ++)
13     {
14         int id = str[i] - '0';
15         if(!trie[root][id])
16             trie[root][id] = ++ tot;
17         root = trie[root][id];
18         sum[root] ++;
19     }
20     k_rt[++ cnt] = root; //记录每个01字符串结束的位置 
21 }
22 
23 void init()
24 {
25     mem(trie, 0);
26     mem(k_rt, 0);
27     mem(sum, 0);
28     cnt = 0, tot = 0;
29 }
30 
31 int main()
32 {
33     int k = 1, flag;
34     while(scanf("%s", str) != EOF)
35     {
36         if(str[0] != '9')
37             insert();
38         else
39         {
40             flag = 0;
41             for(int i = 1; i <= cnt; i ++)
42             {
43                 if(sum[k_rt[i]] >= 2)
44                 {
45                     flag = 1;
46                     break;
47                 }
48             }
49             if(flag)
50                 printf("Set %d is not immediately decodable\n", k ++);
51             else
52                 printf("Set %d is immediately decodable\n", k ++);
53             init();
54         }
55     }
56     return 0;
57 }
HDU1305

 

HDU1671:http://acm.hdu.edu.cn/showproblem.php?pid=1671

题目大意:与HDU1251是一样的

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define mem(a, b) memset(a, b, sizeof(a))
 4 
 5 char str[15];
 6 int trie[100010][12], tot, cnt, k_rt[100010], sum[100010];
 7 
 8 void insert()
 9 {
10     int len = strlen(str);
11     int root = 0;
12     for(int i = 0; i < len; i ++)
13     {
14         int id = str[i] - '0';
15         if(!trie[root][id])
16             trie[root][id] = ++ tot;
17         root = trie[root][id];
18         sum[root] ++;
19     }
20     k_rt[++ cnt] = root; //记录每个字符串的结束位置 ,通过结束位置上的出现次数判断是否是其他字符串的前缀 
21 }
22 
23 void init()
24 {
25     mem(trie, 0);
26     mem(sum, 0);
27     mem(k_rt, 0);
28     tot = 0, cnt = 0;
29 }
30 
31 int main()
32 {
33     int T, n, flag;
34     scanf("%d", &T);
35     while(T --)
36     {
37         init();
38         flag = 0;
39         scanf("%d", &n);
40         getchar();
41         for(int i = 1; i <= n; i ++)
42         {
43             scanf("%s", str);
44             insert();
45         }
46         for(int i = 1; i <= cnt; i ++)
47         {
48             if(sum[k_rt[i]] >= 2)
49             {
50                 flag = 1;
51                 break;
52             }
53         }
54         if(flag)
55             printf("NO\n");
56         else
57             printf("YES\n");
58     }
59     return 0;
60 }
HDU1671

 模板

字典树建树模板:

 1 //建trie树 
 2 void insert()
 3 {
 4     int len = strlen(str);
 5     int root = 0;
 6     for(int i = 0; i < len; i ++)
 7     {
 8         int id = str[i] - '0';
 9         if(!trie[root][id])
10             trie[root][id] = ++ tot;
11         root = trie[root][id];
12         sum[root] ++; //记录数目则需要 
13     }
14     pos[++ cnt] = root; //记录每个字符串的结束位置 ,通
15     //                    过结束位置上的出现次数判断是否是其他字符串的前缀 
16 }   //                     若根据输入判断,则不需要这句话,查找输入的字符串最后一个位置的出现次数即可 
建trie树

字典树查找模板:

 1 //trie树查找 
 2 int serach()//bool serach() , 该字符串为前缀的数目/是否存在以该字符串为前缀的字符串 
 3 {
 4     int len = strlen(str);
 5     int rt = 0;
 6     for(int i = 0; i < len; i ++)
 7     {
 8         int id = str[i] - 'a';
 9         if(!trie[rt][id])
10             return 0;//return false;
11         rt = trie[rt][id];
12     }//达到字符串最后一个字符所在位置 
13     return sum[rt]; // return true;
14 }
字典树查找

 

转载于:https://www.cnblogs.com/yuanweidao/p/11188400.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值