// 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)); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-16 22:52:48