题目描述:先说明此题只有一个测试实例,然后输入一系列的单词,以一个回车为结束符,然后输入一个字符串,要你查找以这个字符串为前缀的单词的个数,处理到文件结束。
解题报告:一开始看到这题,竟然直接用暴力去解了,根本没有想到用字典树,因为字典树是很久以前学的了,刚学的时候一个题都没做,所以现在都忘了,还好这题一次就写出来了,还没有调试,用字典树,要注意的是,一般字典树是在每个点标记有没有以这个点没结束的单词,但是这里要将每个节点标记的成经过这个节点的次数,因为可能有多个单词的前缀相同,这样就会多次经过这个点,如果只标记是否走过的话,就没有办法统计次数了。代码附上:
1 #include<cstdio> 2 #include<cstring> 3 4 typedef struct node { 5 char c; 6 int flag; 7 node *next[26]; 8 node() { //各种初始化 9 flag = 0; 10 for(int i = 0;i<26;++i) 11 next[i] = NULL; 12 } 13 }Trie; 14 void push(Trie *head,char *s) { //插入字符串 15 int len = strlen(s); 16 Trie *p = head; 17 for(int i = 0;i<len;++i) { 18 if(p->next[s[i]-'a'] == NULL) { 19 p->next[s[i]-'a'] = new Trie; 20 p->next[s[i]-'a']->c = s[i]; 21 p->next[s[i]-'a']->flag++; //这里要注意因为插入的字符串前缀相同的可能有多个,所以应该统计个数,而不是标记是否存在 22 p = p->next[s[i]-'a']; 23 } 24 else if(p->next[s[i]-'a'] != NULL) { 25 p->next[s[i]-'a']->flag++; 26 p = p->next[s[i] -'a']; 27 } 28 } 29 } 30 int serch(Trie *head,char *s) { 31 int len = strlen(s); 32 Trie *p = head; 33 for(int i = 0;i<len;++i) { 34 if(p->next[s[i]-'a'] == NULL) 35 return 0; //不能走到末尾的字符,直接返回0; 36 else p = p->next[s[i]-'a']; 37 if(i == len-1) 38 return p->flag; 39 } 40 } 41 void Delete(Trie *head) { 42 Trie *p = head; 43 for(int i = 0;i<26;++i) { 44 if(p->next[i] != NULL) 45 p = p->next[i]; 46 else { 47 delete p; 48 return ; 49 } 50 } 51 } 52 53 54 int main() { 55 Trie *head = new Trie; 56 char s[12]; 57 while(gets(s)) 58 if(s[0] != NULL) 59 push(head,s); 60 else break; 61 while(scanf("%s",s)!=EOF) 62 printf("%d ",serch(head,s)); 63 Delete(head); //清理内存 64 return 0; 65 }