统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 39200 Accepted Submission(s): 14274
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana band bee absolute acm ba b band abc
Sample Output
2 3 1 0
这个题就是建立普通的字典树,首先读入单词,建立树,然后每行一个询问,输出以这个询问为前缀的单词数量(若单词本身就是前缀,那么这个单词也要计数)。
处理数据时注意:1.以一空行作为单词输入结束.
2.若用静态数组的方法建树,数组要开大点,比如500000,开小了就是runtime error
第一种方法:静态数组法
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int MAX=26; const int MAXN=500000; int tree[MAXN][MAX]; int val[MAXN]; int node; void Insert(char s[]) { int i,tmp; int rt=0; for(i=0; s[i]; i++) { tmp=s[i]-'a'; if(tree[rt][tmp]==0) { tree[rt][tmp]=++node; } rt=tree[rt][tmp]; val[rt]++; } } int Search(char s[]) { int rt=0; int i=0,tmp; while(s[i]) { tmp=s[i]-'a'; i++; if(tree[rt][tmp]==0)return 0; rt=tree[rt][tmp]; } return val[rt]; } int main() { int i; node=0; char str[22]; memset(val,0,sizeof(val)); memset(tree,0,sizeof(tree)); while(gets(str),strcmp(str,"")) Insert(str); while (gets(str)) { printf("%d ", Search(str)); } return 0; }
第二种方法:指针法建树
#include<string.h> #include<iostream> #include<stdio.h> using namespace std; struct node { bool is; int cnt; node *next[27]; node() { is=false; cnt=0; memset(next,0,sizeof(next)); } }; void Insert(node *rt,char s[]) { node *p=rt,*newnode; int i=0,tmp; int ok=1; for(i=0; i<strlen(s); i++) { tmp=s[i]-'a'; if(p->next[tmp]==NULL) { newnode=new node(); p->next[tmp]=newnode; } p=p->next[tmp]; p->cnt++; } p->is=true ; } int Search(node *rt,char s[]) { node *p=rt; int i=0,tmp; for(i=0; i<strlen(s); i++) { tmp=s[i]-'a'; if(p->next[tmp]==NULL)return 0; p=p->next[tmp]; } return p->cnt; } int main() { int i=0; node *rt=new node(); char str[20]; while(gets(str),strcmp(str,"")) Insert(rt,str); while(gets(str)!=NULL) printf("%d ",Search(rt,str)); return 0; }
第三种方法:可以使用map的方法(看别的网友代码时发现的)
#include <cstdio> #include <iostream> #include <map> #include <cstring> #include <string> using namespace std; int main() { char str[17]; map<string, int> m; while(gets(str)) { int len = strlen(str); if (!len) { break; } for(int i = len; i > 0; i--) { str[i] = ' '; m[str]++; } } while(gets(str)) { cout<<m[str]<<endl; } return 0; }