您的位置:首页 > 理论基础 > 数据结构算法

HDU 1251 统计难题 (字典树)

2015-10-08 22:32 232 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251

题面:


统计难题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)

Total Submission(s): 25921    Accepted Submission(s): 10560


Problem Description

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

 

Input

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

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

 

Output

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

 

Sample Input

banana
band
bee
absolute
acm

ba
b
band
abc

 

Sample Output

2
3
1
0

题意:

   额,中文大家都懂。

解题:

    字典树裸题,val值统计经过该点的字母数量。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
struct Trie
{
//用来储存该节点的26个字母下标,ch的第一维要注意,要开大,不然会T
int ch[1000010][26];
//val数组一般用来存储权值,视题目灵活运用,sz是当前节点数量
int val[1000010],sz;
//初始化
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
}
//插入一条单词
void insert(string s)
{
//u是节点编号,并不是层数
int u=0,len=s.length();
for(int i=0;i<len;i++)
{
//取下标
int c=(s[i]-'a');
//如果该节点不存在,创建该节点
if(!ch[u][c])
{
//真的是相当的省
memset(ch[sz],0,sizeof(ch[sz]));
//因为刚创建所以为1
val[sz]=1;
//给该节点分配编号
ch[u][c]=sz++;
//下移
u=ch[u][c];
}
//已经存在了
else
{
//下移,并计数值加一
u=ch[u][c];
val[u]++;
}
}
}
//查询前缀
int query(string s)
{
int len=s.length(),u=0,c;
//不断下移,直至移到给定的前缀的最后一个单词
bool sign=true;
for(int i=0;i<len;i++)
{
c=s[i]-'a';
if(ch[u][c])
u=ch[u][c];
else
{
sign=false;
break;
}
}
if(sign)
return val[u];
else
return 0;
}
};
Trie T;
int main()
{
string s;
T.init();
while(getline(cin,s))
{
if(s=="")break;
T.insert(s);
}
while(getline(cin,s))
{
cout<<T.query(s)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息