// 题目:hdu_2222
// 地址:http://acm.hdu.edu.cn/showproblem.php?pid=2222
// 状态:Accept
/**
* 这题是用字典树做的,效率不太高,其中还有很多地方有待优化
*
* 缺陷:每个实例都重新建一颗字典树,没有释放资源,如果测试实例太多,将占用大量内存。
*/
#include <stdio.h>
#include <string.h>
struct node{
int times; //此关键词出现的次数
node * child[26];
bool over; //关键词是否结束(当前结点之前的是否构成一个关键字)
node()
{
times = 0;
memset(child, 0, sizeof(child));
over = false;
}
};
char keywords[55];
char description[1000000];
void add(char * str, node * next)
{
//往树中加入关键字
//问题:怎样记录所有子树的个数? 查福大凯撒密码II
//node * next = root;
while(*str)
{
if(next->child[*str-'a'] == NULL)
next->child[*str-'a'] = new node();
//next->child_num++;
next = next->child[*str-'a'];
str++;
}
next->times++;
next->over = true;
}
int query(char * str, node * root)
{
//返回查找到的关键词的数量
node * next;
char * tmp;
int sum = 0;
while(*str)
{
tmp = str;
next = root;
while(*tmp)
{
if(next->child[*tmp-'a'] != NULL)
next = next->child[*tmp-'a'];
else
break;
if(next->over)
sum += next->times;
//首次访问完就把这个关键词从树中删除
next->over = false;
tmp++;
}
str++;
}
return sum;
}
int main(void)
{
//freopen("E:\\input.txt", "r", stdin);
int p, n;
scanf("%d", &p);
while(p--)
{
scanf("%d", &n);
node * root = new node();
while(n--)
{
scanf("%s", keywords);
add(keywords, root);
}
memset(description, 0, sizeof(description));
scanf("%s", description);
printf("%d\n", query(description,root));
delete root;
}
return 0;
}
/**
* 易错测试数据
* 1
* h
* hhhhh
* 结果是1,因为只有一个关键字h,而字符串中出现了4次h,但是算做重复,只计数一次
*------------------------------------------
* 2
* a
* a
* a
* 结果是2,因为keywords中a 出现了两次
*------------------------------------------
* 只要能处理这两组数据,其他的问题不大
*/
hdu_OJ_2222
最新推荐文章于 2021-05-05 19:51:51 发布