统计难题

C - 统计难题
Time Limit:2000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u

Description

Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). 
 

Input

输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 

注意:本题只有一组测试数据,处理到文件结束. 
 

Output

对于每个提问,给出以该字符串为前缀的单词的数量. 
 

Sample Input

     
     
banana band bee absolute acm ba b band abc
 

Sample Output

     
     
2 3 1 0
第二次做这题了,好久没接触trie树,好多知识都忘了。一开始感觉是直接最长的字母长度为深度,一直向下写就行了。但是一直没结果,原来是我没理解。因为如果是动态的话,他是26叉树,所以肯定有很多节点,要开很大的空间才行。
静态版:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
#define T 500005
#define inf 0x3f3f3f3f
#define CRL(a) memset(a,0,sizeof(a))
typedef long long ll;
struct trie
{
	int v;
	int kid[26];
	trie()
	{
		v=0;CRL(kid);
	}
}tr[T];
char s[T]; 
int c=1;
void insert()
{
	int i,x=0,d;
	for(i=0;s[i];++i){
		d = s[i]-'a';
		if(tr[x].kid[d]==0){
			tr[x].kid[d]=c++;
			x=c-1;
		}
		else
		x = tr[x].kid[d];
		tr[x].v++;
	}
}
int find()
{
	int i,x=0,d;
	for(i=0;s[i];++i){
		d = s[i]-'a';
		if(tr[x].kid[d]==0)
			return 0;
		x = tr[x].kid[d];
	}
	return tr[x].v;
}
int main()
{
	/*freopen("input.txt","r",stdin);*/
	while(cin.getline(s,T)&&s[0]!='\0')
	{
		insert();
	}
	while(cin.getline(s,T))
	{
		printf("%d\n",find());
	}
	return 0;
}




这题非常的水但是就是整天内存超限。让我非常不爽的是根本就是编译器的问题,用G++提交肯定超限,用c++就不超了,还有就是感谢杭电里面的讨论,让我知道为什么总是优化不出来,原来是系统问题。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
struct S
{
	int value;
	S* kid[26];
	S()
	{
		value=0;
		for(int i=0;i<26;++i)
		{
			kid[i]=NULL;
		}
	}
}*root;
void insert(char* str)
{
	S* t=root;
	int d;
	for(int i=0;str[i];++i)
	{
		d=str[i]-'a';
		if(t->kid[d]==NULL)
		{
			t->kid[d] = new S;
		}
		t=t->kid[d];
		t->value++;
	}
}
int find(char* str)
{
	S* t = root;
	int d;
	for(int i=0;str[i];++i)
	{
		d = str[i]-'a';
		if(t->kid[d]==NULL)
		{
			return 0;
		}
		t = t->kid[d];
	}
	return t->value;
}
int main()
{
	char str[15];
	root = new S;
	while(gets(str)&&str[0])
	{
		insert(str);
	}
	while(~scanf("%s",&str))
	{
		printf("%d\n",find(str));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值