HDU1251 统计难题[map的应用][Trie树]

一、题意

给出一组单词,另给出一组单词用作查询,求解对于每个用于查询的单词,前一组中有多少个单词以其为前缀。

二、分析

根据题目很容易想到hash的方法,首先可以朴素的考虑将第一组中的所有单词的前缀利用map进行统计,查询时直接得到结果

所以很容易可以得到以下代码。

注意:输入时的空行代表第一行的结束,利用gets读入并根据字符串的长度是否为0来判断;

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <map>
 5 using namespace std;
 6 const int maxn = 15;
 7 char word[maxn];
 8 map<string,int> M;
 9 int main()
10 {
11     while(gets(word))
12     {
13         if(strlen(word) == 0)
14             break;
15         int L = strlen(word);
16         for(int i=L;i>0;i--)
17         {
18             word[i] = '\0';
19             M[word]++;
20         }
21     }
22     while(gets(word))
23         printf("%d\n",M[word]);
24     return 0;
25 }
View Code

 然而,有些题目会卡map的用法,需要找到更高效的算法,这里可以使用Trie树,也就是前缀树、字典树来解决问题。

字典树的根节点为空,用边来表示字母,用根节点到某个节点的路径表示一个单词,字典树可以用数组表示,其中Tree[root][i]=k表示树上位置标号为root的节点的第i个子节点的位置编号为k

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 const int maxn = 2e6+5;
 6 int Tree[maxn][30],sum[maxn];
 7 int cnt;
 8 void Insert(char word[])
 9 {
10     int L = strlen(word);
11     int root = 0;
12     for(int i=0;i<L;i++)
13     {
14         int id = word[i] - 'a';
15         if(!Tree[root][id])
16             Tree[root][id] = ++cnt;
17         sum[Tree[root][id]]++;
18         root = Tree[root][id];
19     }
20 }
21 int Find(char word[])
22 {
23     int L = strlen(word);
24     int root = 0;
25     for(int i=0;i<L;i++)
26     {
27         int id = word[i] - 'a';
28         if(!Tree[root][id])
29             return 0;
30         root = Tree[root][id];
31     }
32     return sum[root];
33 }
34 int main()
35 {
36     char word[15];
37     cnt = 0;
38     while(gets(word))
39     {
40         if(strlen(word) == 0)
41             break;
42         Insert(word);
43     }    
44     while(scanf("%s",word)!=EOF)
45         printf("%d\n",Find(word));
46     return 0;
47 }
View Code

注意,如果第二组单词用scan读入记得写!=EOF的形式

转载于:https://www.cnblogs.com/cnXuYang/p/10280268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值