杭电OJ 1251 、1671(字典树)

来源:互联网 发布:域名冲突怎么解决 编辑:程序博客网 时间:2024/04/28 04:16

杭电OJ 1251

题目传送门:

1251  统计难题:http://acm.hdu.edu.cn/showproblem.php?pid=1251

1671,Phone List: http://acm.hdu.edu.cn/showproblem.php?pid=1671

用标准的Trie树即可解决。

字典树单词查找树Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。 具体参见我之前的 csdn blog 字典树。

解决代码如下(G++编译):

1251:

#include <stdio.h>#include <string.h>#include <stdlib.h>#define max 26 //此函数只考虑26个英文字母的情况typedef struct Node{int v;//v可以表示一个字典树到此有多少相同前缀的数目struct Node *next[max];//是表示每层有多少种类的数,如果只是小写字母,则26即可,若改为大小写字母,则是52Node()// 构造函数{v = 0;memset(next, 0, sizeof(next));}}Trie;void insert(Trie * root, char *str)//trie树插入结点{if(root ==NULL || str == NULL)return ;int i;Trie *t = root;char *p = str;for(i=0; str[i] != '\0'; i++){if(t->next[*p - 'a'] == NULL)t->next[*p - 'a'] = new Trie();t = t->next[*p - 'a'];t->v++;++p;}}void search(Trie *root, char *str)//查找串是否在该trie树中{if(root ==NULL || str == NULL)return ;int i;Trie *t = root;char *p = str;for(i=0; str[i] != '\0'; i++){if(t->next[*p - 'a'] != NULL){t=t->next[*p - 'a'];}elsebreak;++p;}if(*p != '\0')printf("0\n");else{printf("%d\n", t->v);}}int main(){Trie *root = new Trie();//freopen("input.txt","r",stdin);char str[32];while(gets(str) && str[0] != '\0')//gets能输入空格,而scanf不行.str[0]判断是否到换行insert(root, str);while(scanf("%s",str) != EOF)search(root, str);return 0;}

1671:

#include <stdio.h>#include <string.h>#include <Cstdlib>#define max 10typedef struct Node{bool flag;// 表示某个号码是否出现过struct Node *next[max];// 每一层出现的号码可能种类Node(){flag = false;memset(next,0,sizeof(next));}}Trie;bool test(Trie *root, char *str)// insert and test {if( root == NULL || str == NULL)return false;int i;char *p= str;Trie *t = root;for(i=0; str[i]!='\0'; i++){if(t->next[*p-'0'] == NULL){t->next[*p-'0'] = new Trie();}else// 已存在此前缀{if(t->next[*p-'0']->flag)// 某个号码为此号码的前缀return false;if(str[i+1] == '\0') // 达到此号码末尾,但是为某个号码的前缀return false;}t = t->next[*p-'0'];++p;}t->flag = true;return true;}void del(Trie *root){if(!root)return ;for(int i=0; i<max; i++){if(root->next[i])del(root->next[i]);}free(root);}int main(){freopen("in.txt", "r", stdin);int t,n;bool valid;//电话号码列表是否有效char str[12];Trie *root;scanf("%d", &t);while(t--){root = new Trie();valid = true;scanf("%d", &n);while(n--){scanf("%s",str);if(valid)valid = test(root, str);}if(valid)printf("YES\n");elseprintf("NO\n");del(root);}return 0;}
原创粉丝点击