hdu-1251 统计难题---字典树
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1251
题目大意:
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
解题思路:
将每个单词存入字典树中,直接查询前缀出现次数即可,在加入字典树的时候,在每个字母表示的边上后面的节点数加1,记录前缀出现次数。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<map> 6 #include<set> 7 #include<cmath> 8 #include<algorithm> 9 #include<vector> 10 #include<sstream> 11 #define lowbot(i) (i&(-i)) 12 using namespace std; 13 14 const int maxn = 1e6 + 10; 15 int tree[maxn][26]; 16 //字典树tree[u][v]表示编号为u的节点的下一个字母为v连接的节点的编号 17 int idx(char c){ return c - 'a'; }//可以写成宏定义 18 int tot = 1;//根节点编号为1 19 int sum[maxn];//标记以该节点结束的前缀出现次数 20 void Insert(char s[], int u)//u表示根节点 21 //插入字符串s 22 { 23 for(int i = 0; s[i]; i++) 24 { 25 int c = idx(s[i]); 26 if(!tree[u][c]) 27 tree[u][c] = ++tot; 28 sum[tree[u][c]]++; //前缀后面的那个节点数目加一 29 u = tree[u][c]; 30 } 31 } 32 33 int Find_sum(char s[], int u) 34 { 35 for(int i = 0; s[i]; i++) 36 { 37 int c = idx(s[i]); 38 if(!tree[u][c])return 0; 39 u = tree[u][c]; 40 } 41 return sum[u];//返回最后一个字母表示的边连接的后面那个节点,所记录的sum值 42 } 43 int main() 44 { 45 char s[15]; 46 while(gets(s) && strlen(s))Insert(s, 1); 47 while(scanf("%s", s) != EOF) 48 { 49 printf("%d\n", Find_sum(s, 1)); 50 } 51 return 0; 52 }
越努力,越幸运