Trie
很好理解,就是根据字母存结点(一般26个),从根节点不断往下,记录单词这样子的,仿佛一个方便查找的字典鸭
HDU1251
统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 55631 Accepted Submission(s): 19431
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2 3 1 0
数组实现
不如指针直观,将结点编号化了,速度相较之下貌似会快一些,空间大概会开的多一点这样子(如果开结构体会比较系统但相对也有一定局限性,占空间貌似也多一点儿,写在外面一样的
#include <cstdio>
#include <cstring>
const int maxnode=1000000;
const int alphanum=26;
int ch[maxnode][alphanum]; //ch[i][j]表示编号为i的第j个孩子的编号
int val[maxnode]; //val[i]记录编号为i的节点信息
struct Trie
{
int num; //编号
//int ch[maxnode][alphanum]; //ch[i][j]表示编号为i的第j个孩子的编号
//int val[maxnode]; //val[i]记录编号为i的节点信息
Trie()
{
num=1; //根节点编号为0
memset(ch[0],0,sizeof(ch[0]));
}
void Insert(char* s,int v)
{
int u=0,n=strlen(s);
for(int i=0;i<n;++i){
int c=s[i]-'a';
if(!ch[u][c]){ //结点不存在
memset(ch[num],0,sizeof(ch[num]));
val[num]=0; //清空
ch[u][c]=num++;
}
u=ch[u][c]; //往下走
val[u]++;
}
; //最后一个字符储存信息
}
int query(char* s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;++i){
int c=s[i]-'a';
if(!ch[u][c]){ //字典树中未储存字符串s
return 0;
}
u=ch[u][c]; //往下走
}
return val[u]; //找到并返回信息
}
};
const int maxw=15;
int main()
{
char str[maxw],pre[maxw];
Trie t;
while(1){
gets(str);
if(str[0]=='\0')
break;
t.Insert(str,0);
}
while(~scanf("%s",pre)){
printf("%d\n",t.query(pre));
}
return 0;
}
指针实现
会比较直观,写起来会有一点复杂的感觉,全是->嘛,但如果题目复杂,要求复杂,写指针还是很好的,而且在一定情况下,复杂度也会很优秀的感觉。
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int wlength=10;
const int alphanum=26;
struct TrieNode{
int count; //经过此节点数目
TrieNode *Next[alphanum];
TrieNode(int x):count(x){
for(int i=0;i<alphanum;++i){
Next[i]=NULL;
}
}
};
//插入
void Insert(TrieNode* &root,char* str)
{
int size=strlen(str);
int val;
TrieNode *p=root;
for(int i=0;i<size;++i){
val=str[i]-'a';
if(p->Next[val]==NULL){
p->Next[val]=new TrieNode(0);
}
p=p->Next[val];
p->count++;
}
}
//查找
int Search(TrieNode* &root,char* str)
{
if(root==NULL)
return 0;
int size=strlen(str);
TrieNode *p=root;
int val;
for(int i=0;i<size;++i){
val=str[i]-'a';
if(p->Next[val]==NULL){
return 0;
}
p=p->Next[val];
}
return p->count;
}
int main()
{
TrieNode *root=new TrieNode(0);
memset(root,0,sizeof(root));
char s[wlength],ss[wlength];
int num;
while(1)
{
gets(s);
if(s[0]=='\0')
break;
Insert(root,s);
}
while(~scanf("%s",ss))
{
num=Search(root,ss);
printf("%d\n",num);
}
return 0;
}