HDU - 1251 - 统计难题

题目:

统计难题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 14095    Accepted Submission(s): 6070


Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
 

 

Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.
 

 

Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 

 

Sample Input
banana
band
bee
absolute
acm
 
ba
b
band
abc
 

 

Sample Output
2
3
1
0
 
  题意不解释,这题RE+MLE+WA一共16次= =,主要是对Trie不太熟悉。首先我用的是静态链表,RE的主要原因是数组成二维了,这一点一开始没有考虑到,是因为没有仔细把大白书上面的模板看完,以为用来标记的数组应该也是二维的,这样才合逻辑,虽然小数据的话没有出问题,但是数据大到一定情况的话就会RE,这是就会认为是不是数组开得不够大,于是继续加大,接着就是MLE了= =。
  用来标记的附加数组这里只需要使用一维的就可以,为什么?因为这里字典树的本体用的是一个二维数组,其中一维是用来表示某个前缀的下一个字母有可能是哪些(这里这种解释似乎有点不是很准确,建议去看一下Trie树的构成),另一维是用来表示可以最多可以保存多少个字母的长度(这种说法也好像不是很准确)。附加数组的规模需要和字典树的另一维一样大,这样才可以起作用。其实就是把静态链表的结构看成指针链表(就是把原本整齐的内存结构看成游离的内存块,这样说似乎更加生动,容易理解= =) 那么附加数组就像是紧贴Trie数的一条链,它的作用就是标明某个位置就是一个字符串的结束,就像字符串末尾的'\0'一样。
  至于上面说的规模需要开多大,我觉得这里需要根据问题来决定,如果他说有10000个字符串,每个字符串最长就有10的长度,每个位置有10种字符出现的可能的话,规模大概就需要10000*10*10以上了,这里我暂时还不是很确定,有可能可以小一点。
 
 
 
代码:
 1 #include <stdio.h>
 2 #include <string.h>
 3 #define MAX 500000
 4 using namespace std;
 5 
 6 int s[MAX][26],count[MAX],tot;
 7 
 8 void Init()
 9 {
10     memset(s[0],0,sizeof(s[0]));
11     memset(count,0,sizeof(count));
12     tot=1;
13 }
14 
15 void Insert(char *c)
16 {
17     int i,j,u,n;
18     n=strlen(c);
19     j=0;
20     for(i=0;i<n;i++)
21     {
22         u=c[i]-'a';
23         if(!s[j][u])
24         {
25             memset(s[tot],0,sizeof(s[tot]));
26             count[tot]=0;
27             s[j][u]=tot++;
28         }
29         j=s[j][u];
30         count[j]++;
31     }
32 }
33 
34 
35 int Query(char *c)
36 {
37     int i,j,u,n;
38     n=strlen(c);
39     j=0;
40     if(n>20) return 0;
41     for(i=0;i<n;i++)
42     {
43         u=c[i]-'a';
44         if(!s[j][u]) return 0;
45         if(i+1==n) break;
46         j=s[j][u];
47     }
48     return count[s[j][u]];
49 }
50 
51 int main()
52 {
53     int ans;
54     char c[100];
55     Init();
56     while(gets(c),c[0]!='\0')
57     {
58         Insert(c);
59     }
60     while(gets(c))
61     {
62         ans=Query(c);
63         printf("%d\n",ans);
64     }
65     return 0;
66 }
1251

 

posted @ 2013-09-02 17:02  海拉鲁的林克  阅读(624)  评论(0编辑  收藏  举报