hdu 2846 Repository 字典树的一种变形

Repository

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2633    Accepted Submission(s): 1028


Problem Description
When you go shopping, you can search in repository for avalible merchandises by the computers and internet. First you give the search system a name about something, then the system responds with the results. Now you are given a lot merchandise names in repository and some queries, and required to simulate the process.
 

Input
There is only one case. First there is an integer P (1<=P<=10000)representing the number of the merchanidse names in the repository. The next P lines each contain a string (it's length isn't beyond 20,and all the letters are lowercase).Then there is an integer Q(1<=Q<=100000) representing the number of the queries. The next Q lines each contains a string(the same limitation as foregoing descriptions) as the searching condition.
 

Output
For each query, you just output the number of the merchandises, whose names contain the search string as their substrings.
 

Sample Input
   
   
   
   
20 ad ae af ag ah ai aj ak al ads add ade adf adg adh adi adj adk adl aes 5 b a d ad s
 

Sample Output
   
   
   
   
0 20 11 11 2


我的AC状态,,我总感觉自己好笨的。。脑子不太灵活,第一次写的时候超时了,,来说一下思路吧,,就是把一个字符串abcde,分别拆成abcde,bcde,cde,de,e,存到字典树里,因为会出现会abcab这样的字符串,他的字串有俩个ab开头的,,所以得在结构体里加上一个id标签,,把id设为最后一个存到字典树里的字符串。看代码就知道啦,很容易懂的

下面是AC代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20000
struct Trie{
	int count;		//储存相同字符串的数目 
	int id ;		//标识已储存过的字符串,防止重复计算。 
	Trie *next[26];
};

//建树 
void build(Trie *t , char name[] , int id)
{
	int len =strlen(name) ;
	for(int i = 0 ; i < len; ++i)
	{
		if(t->next[name[i]-'a'] == NULL)
		{
			Trie *temp = (Trie*)malloc(sizeof(Trie)) ;
			temp->count=1;
			temp->id = id ;
			for(int j = 0 ; j < 26 ; ++j)
			{
				temp->next[j] = NULL ;
			}
			t->next[name[i]-'a'] = temp ; 
			t = temp ;
		}
		else
		{
			t = t->next[name[i]-'a'] ;
			if(id != t->id)
				t->count ++;
			t->id = id ;
		}
		
	}
}
int count = 0 ;
bool flag[MAX] ;
//查询 
void query(Trie *t , char str[])
{
	int len = strlen(str) , i ;
	for(i = 0 ; i < len ; ++i)
	{
		if(t->next[str[i]-'a'] != NULL)
		{
			t = t->next[str[i]-'a'] ;
		}
		else
		{
			break ;
		}
	}
	if( i == len )
	{
		if(!flag[t->id])
		{
			count += t->count ;
			flag[t->id] = true ;
		}
	}
}

int main()
{
	int n ;
	scanf("%d",&n);
	Trie *t=(Trie *)malloc(sizeof(Trie));
	for(int i = 0 ; i < 26 ; ++i)
	{
		t->next[i] = NULL ;
	}
	t->count = 0 ;
	for(int i =0 ; i < n ; ++i)
	{
		char name[30];
		scanf("%s",name) ;
		int len = strlen(name) ;
		for(int j = 0 ; j < len ; ++j)
		{
			build(t,name+j,i);
		}
	}
	int q;
	scanf("%d",&q);
	for(int i = 0 ; i < q ; ++i)
	{
		memset(flag,0,sizeof(flag)) ;
		char str[30];
		count = 0 ;
		scanf("%s",str);
		query(t,str) ;
		printf("%d\n",count) ;
	}
	return 0 ;
}

//严格的来说,如果是测试多组测试数据,,应该释放内存,,但是就一组测试数据,释不释放都无所谓啦!下面超时的代码里有释放内存的函数,如果想知道怎么释放,可以参考下面的代码。



下面是第一次超时的代码,,大家可以无视跳过。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Trie{
	int count;
	Trie *next[26];
};

void build(Trie *t , char name[])
{
	int len =strlen(name) ;
	for(int i = 0 ; i < len; ++i)
	{
		if(t->next[name[i]-'a'] == NULL)
		{
			Trie *temp = (Trie *)malloc(sizeof(Trie)) ;
			temp->count=1;
			for(int j = 0 ; j < 26 ; ++j)
			{
				temp->next[j] = NULL ;
			}
			t->next[name[i]-'a'] = temp ; 
			t = temp ;
		}
		else
		{
			t = t->next[name[i]-'a'] ;
			t->count ++;
		}
		
	}
}
int count = 0 ;
void query(Trie *t , char str[],int index)
{
	if(index == strlen(str))
	{
		count += t->count ;
		return ;
	}
	for(int i = 0 ; i < 26 ; ++i)
	{
		if(t->next[i] != NULL)
		{
			if(i == str[index]-'a')
			{
				query(t->next[i],str,index+1);
			}
			else
			{
				query(t->next[i],str,0) ;
			}
		}
	}
}

void destroy(Trie *t)
{
	for(int i = 0 ; i < 26 ; ++i)
	{
		if(t->next[i] != NULL)
			destroy(t->next[i]) ;
	}
	free(t);
}

int main()
{
	int n ;
	scanf("%d",&n);
	Trie *t=(Trie *)malloc(sizeof(Trie));
	for(int i = 0 ; i < 26 ; ++i)
	{
		t->next[i] = NULL ;
	}
	t->count = 0 ;
	for(int i =0 ; i < n ; ++i)
	{
		char name[30];
		scanf("%s",name) ;
		build(t,name);
	}
	int q;
	scanf("%d",&q);
	for(int i = 0 ; i < q ; ++i)
	{
		char str[30];
		count = 0 ;
		scanf("%s",str);
		query(t,str,0) ;
		printf("%d\n",count) ;
	}
	destroy(t) ;
	return 0 ;
}

可能这个代码没什么用,就作为给自己的一个警告吧!



你可能感兴趣的:(ACM,repository,字典树,字典树的一种变形,hdu2846)