杭电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 字典树。
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即可,若改为大小写字母,则是52
Node()// 构造函数
{
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'];
}
else
break;
++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 10
typedef 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");
else
printf("NO\n");
del(root);
}
return 0;
}