hdu 2846 Repository

查询单词是否存在于上面的所有单词中,输出存在的单词数。

因为数量很大啊,所以不能枚举,然后就想到字典树了。但是肯定不能建一棵,因为查询的单词可能是从中间开始的。

所以就枚举单词的每个字母作为起点,剩下的去建树,每个字母建成一棵树,这样的话,查找的代价就是单词的长度。

不过内存需要开很大,MLE了数次= = 。。。好久没写字典树了。。。还算顺利吧。


#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>

using namespace std;

const int MAX = 10001*50;
typedef struct NODE{
	int cnt,ind;
	NODE *next[26];
}NODE;
NODE *a[26],node[MAX];
int cou;
void init()
{
	memset(node,0,sizeof(node));
	cou = 27;
	for(int i=0; i<26; i++)
		a[i] = &node[i];
}
void Add(char *s,int n,int ind)
{
	NODE *head = a[s[0]-'a'];
	if( head->ind != ind )
	{
		head->cnt++;
		head->ind = ind;
	}
	for(int i=1; i<n; i++)
	{
		if( head->next[s[i]-'a'] == NULL)
		{
			head->next[s[i]-'a'] = &node[cou++];
			head->next[s[i]-'a']->cnt = 0;
			head->next[s[i]-'a']->ind = 0;
		}
		head = head->next[s[i]-'a'];
		if( head->ind != ind )
		{
			head->cnt++;
			head->ind = ind;
		}
	}
}
int find(char *s,int n)
{
	NODE *head = a[s[0]-'a'];
	for(int i=1; i<n; i++)
	{
		if( head->next[s[i]-'a'] != NULL )
			head = head->next[s[i]-'a'];
		else
			return 0;
	}
	return head->cnt;
}	

int main()
{
	int n,q;
	char str[50];
	while( ~scanf("%d",&n) )
	{
		init();
		for(int i=1; i<=n; i++)
		{
			scanf("%s",str);
			int len = strlen(str);
			for(int k=0; k<len; k++)
				Add(str+k,len-k,i);
		}
		scanf("%d",&q);
		while( q-- )
		{
			scanf("%s",str);
			int ans = find(str,strlen(str));
			printf("%d\n",ans);
		}
	}

return 0;
}


你可能感兴趣的:(hdu 2846 Repository)