HDU–1251题 统计难题
这个题用到了字典树。 这个知识点是栋栋哥上个星期五讲的,其他几个人也都做过这方面的练习,我直到昨天下午才弄字典树的题。速度慢了不止一拍。这两天学校的网速基本就是老乌龟一个档次的,昨天更是神奇的连网页也打不开,所以这篇解题报告直到 现在才写。各位,原谅我的懒惰吧!
简单的写一下自己的思路和感悟。字典树其实是一种非常好用的统计方法,特别是当传统的排序、统计方法浪费了大量时间和内存的情况下。字典树,顾名思义,就是建立一个树,而分叉则是一些字母。我们建立一个节点,储存一个字母,然后再建立另外一个节点,储存另外一个 字母。用链表来链接。可能你会很晕乎,没事,一会我会单独写篇字典树的学习笔记,嘿嘿。
至于这个题,就是直白的字典树的应用,唯一需要注意的就是一些小的细节。我昨天花了2个多小时才弄出这个题目来。各种小错误,弄得很头大。其实就是因为自己没有熟练的掌握这个方法,写的很生硬。
原题地址:HDU 1251题(点击打开)
原题描述:
统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 8549 Accepted Submission(s): 3411
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2
3
1
0
代码如下:(注意一下我写的注释)
01 | #include<stdio.h> |
02 | #include<string.h> |
03 | #include<stdlib.h> |
04 | struct node |
05 | { |
06 | int count ; |
07 | struct node *next[26]; //定义26个分节点 |
08 | }; |
09 | struct node *root; |
10 | struct node *build() //建立节点 |
11 | { |
12 | struct node *p; |
13 | p=( struct node *) malloc ( sizeof ( struct node)); |
14 | for ( int i=0;i<26;i++) |
15 | { |
16 | p->next[i]=NULL; //令其指向0; |
17 | } |
18 | p->count=1; /*如果出现这个站点,那么它的次数肯定是大于等于1的。 |
19 | 但是我们刚开始建立不必考虑后续问题*/ |
20 | return p; //返回新建立的节点 |
21 | } |
22 | void save( char *s) //储存字母 |
23 | { |
24 | int len= strlen (s); |
25 | if (len==0) return ; |
26 | struct node *p; |
27 | p=root; |
28 | for ( int i=0;i<len;i++) |
29 | if (p->next[s[i]- 'a' ]!=NULL) |
30 | /*如果这个节点之前就已经存在呃,我们只需要把统计次数加上1.*/ |
31 | { |
32 | p=p->next[s[i]- 'a' ]; |
33 | p->count=p->count+1; |
34 | } |
35 | else //如果不存在的话,我们就建立一个新的节点 |
36 | { |
37 | p->next[s[i]- 'a' ]=build(); |
38 | p=p->next[s[i]- 'a' ]; |
39 | } |
40 | } |
41 | int seach ( char *s) //这个函数来查询数据 |
42 | { |
43 | struct node *p; |
44 | int len= strlen (s); |
45 | if (len==0) return 0; |
46 | p=root; //此处小心 |
47 | for ( int i=0;i<len ;i++) |
48 | { |
49 | if (p->next[s[i]- 'a' ]!=NULL) //说明还有下个节点,继续查询 |
50 | p=p->next[s[i]- 'a' ]; |
51 | else |
52 | return 0; |
53 | /*如果没有指向下个节点,说明这个要查询的字符串根本不存在,直接返回0*/ |
54 | } |
55 | return p->count; |
56 | } |
57 | int main() |
58 | { |
59 | char str[15]; |
60 | int i,ans; |
61 | root=build(); |
62 | while ( gets (str)&&str[0]!= '\0' ) |
63 | save(str); |
64 | while (~ scanf ( "%s" ,str)) |
65 | { |
66 | ans=seach(str); |
67 | printf ( "%d\n" ,ans); |
68 | } |
69 | return 0; |
70 | } |