题目:
统计难题 |
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others) |
Total Submission(s): 349 Accepted Submission(s): 209 |
Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). |
Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. |
Output 对于每个提问,给出以该字符串为前缀的单词的数量. |
Sample Input banana band bee absolute acm ba b band abc |
Sample Output 2 3 1 0 |
Author Ignatius.L |
Recommend Ignatius.L |
题目分析:
Trie的基本题。这道题提交的时候使用C++提交,使用G++提交会MLE。而且杭电有时候很搞笑的,这道题
很快就敲出来了,提交以后一直TLE。后来中午再交一次的时候,就正常了,在200ms左右。如果TLE了就多交几次吧。。
代码如下:
/*
* b.cpp
*
* Created on: 2015年3月8日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 26;
typedef struct TrieNode{//Trie结点
int prefix;//到当前节点的前缀数
struct TrieNode* next[MAX];//当前节点的孩子节点
}Trie;
/**
* Trie树的插入操作:
* 将字符串s插入到以root为根的字典树中
*
*/
void insert(Trie* root,char* s){
//如果当前的字典树的根为空||要插入的字符串为空
if(root == NULL || *s == '\0'){
return ;//则直接返回
}
Trie* p = root;
while(*s != '\0'){//不断地遍历要插入的字符串的每一个字符
if(p->next[*s - 'a'] == NULL){//如果字典树中还没有该节点,则新建该节点
//新建结点的初始化操作
Trie* temp = (Trie*)malloc(sizeof(Trie));
int i;
for(i = 0 ; i < MAX ; ++i){
temp->next[i] = NULL;
}
temp->prefix = 1;//新建该节点后的前缀数默认为1
p->next[*s-'a'] = temp;//用next指向temp
p = p->next[*s-'a'];//遍历下一个节点
}else{//如果该节点在字典树中已经存在
p = p->next[*s - 'a'];//遍历下一个节点
p->prefix++;//到该节点的前缀数+1
}
s++;//遍历该字符串的下一个字符
}
}
/**
* 在以root为根字典树中寻找以pre为前缀的单词数有多少个
*/
int count(Trie* root,char* pre){
Trie* p = root;
while(*pre != '\0'){//不断地遍历该前缀字符串
if(p->next[*pre - 'a'] == NULL){//如果某一结点的孩子节点中不包含pre当前遍历的字符
return 0;//则表明单词中没有一pre为前缀的单词,直接返回0
}else{//如果当前节点的孩子节点中有pre当前遍历到的字符
//则继续遍历
p = p->next[*pre - 'a'];
pre++;
}
}
return p->prefix;//返回以pre开头的单词数
}
/**
* 字典树的释放操作
*/
void del(Trie* root){
int i;
for(i = 0 ; i < MAX ; ++i){
if(root->next[i] != NULL){
del(root->next[i]);
}
}
free(root);
}
int main(){
char str[11];
//初始化操作
Trie* root = (Trie*)malloc(sizeof(Trie));
int i;
for(i = 0 ; i < MAX ;++i){
root->next[i] = NULL;
}
root->prefix = 0;
while(gets(str)){//不断地读入字符串
if(strcmp(str,"") == 0){//如果当前读入的是空串
break;//则跳出循环
}
insert(root,str);//将当前读到的字符串插入字典树中
}
while(gets(str)){
printf("%d\n",count(root,str));
}
del(root);//如果没有这个操作耗时只有100ms左右。如果加上这个操作耗时将达到200ms左右。
return 0;
}