// hdu 1251 统计难题 字典树
//
// 题目大意:
//
// 有一系列的单词表,以空行结尾,之后会有一些字母串,找出以这些字符串
// 作为前缀的单词的个数
//
//
// 解题思路:
//
// 字典树 Trie,在插入字符串的时候每遇到一个节点,该节点的值++。查找的时候
// 字符串时,如果找到了,那么返回当前的val,否则返回0,因为没有以这个字符串
// 为前缀的单词。
//
//
// 感悟:
//
// 这段时间想学学数据结构,就看了看刘老的大白书,感觉用数组挺巧妙的,就学了学
// 然后自己敲一敲,先开始碰到这题的时候,我还在想查找的模板怎么写,然后自己照
// 插入的模板敲了一遍,确实是类似的。心情大好,而这道题中间的计数还是不太好处
// 理(对于一个刚刚学字典树的人来说),当然,思路都是每次遇到一个能走的点的时候
// 该节点的值++,遇到走不到的节点的时候将将要链接上的点清空,继续走,最后,在
// 根节点的位置++,就表示当前的单词。感觉字典树确实很神奇,而自己还处在懵懂的
// 状态,继续加油吧~FIGHTING
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int max_n = 400009;
struct trie {
int ch[max_n][26];
int val[max_n];
int sz;
void init(){
sz = 1;
memset(ch[0],0,sizeof(ch[0]));
val[0] = 0;
}
int idx(char c){
return c - 'a';
}
void insert(char *s){
int u = 0;
int n = strlen(s);
for (int i=0;i<n;i++){
int c = idx(s[i]);
if (!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
val[u]++;
u = ch[u][c];
}
val[u]++; //遇到根了,将此时的val ++
}
int query(char *s){
int u = 0;
int n = strlen(s);
for (int i=0;i<n;i++){
int c = idx(s[i]);
if (!ch[u][c]){ //没有找到
return 0;
}
u = ch[u][c];
}
return val[u]; //找到了
}
}trie;
int main(){
char s[20];
trie.init();
//freopen("1.txt","r",stdin);
int cnt = 0;
char c;
char x;
while(gets(s) && s[0] != 0){
trie.insert(s);
}
while(scanf("%s",s)!=EOF){
printf("%d\n",trie.query(s));
}
}
hdu 1251 统计难题 字典树
最新推荐文章于 2016-09-11 15:53:52 发布