杭电 2846 字典树变形

题目:

Repository

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


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代码:

//该题是字典树的变形题目,一般字典树能查找某字符串
//出现的次数或者以某些字符串为前缀的字符串出现的次
//数,不能查找该题所描述的情况。故插入字符串时,假
//设字符串为x1x2x3....xn,则插入时以x1为开头插入,以
//x2为开头插入,一直到以xn为开头插入,为避免如abab
//的字符串重复计数,故插入时增加一个标记变量id,若为
//同一个id,则count值不增加,否则增加
#include <iostream>
#include <cstdio>
using namespace std;
struct Tire{//定义字典树
   int count;
   int id;//标记是不是同一个字符串
  struct Tire *tire[26];
}*a;//tire
void init(){//初始化字典树的函数
  a=(Tire*)malloc(sizeof(Tire));//动态分配内存
  a->id=-1;
  for(int i=0;i<26;++i)
	  a->tire[i]=NULL;
}//init
void insert(char ss[],int newid){//字典树的插入函数
   int len=strlen(ss);
   Tire *head=a;
   for(int i=0;i<len;++i){
     int k=ss[i]-'a';
	 if(head->tire[k]==NULL){//无该结点
		 Tire *newhead=new Tire;//分配新的字典树
		 for(int j=0;j<26;++j)
			 newhead->tire[j]=NULL;//初始化新分配的结点
		 newhead->count=0;
		 newhead->id=-1;
		 head->tire[k]=newhead;//结点之间赋值
	 }//if
		 head=head->tire[k];
		 if(head->id!=newid){//如果不是同一个串的话,则count值加1,否则不加,避免重复
		   head->id=newid;
		   head->count++;
		 }
   }//for
}//insert
int search(char ch[]){//字典树的查找函数
  int len=strlen(ch);
  Tire *head=a;
  for(int i=0;i<len;++i){
    int k=ch[i]-'a';
	if(head->tire[k]==NULL)//不存在这样的串,故返回0
		return 0;
	else{
	  head=head->tire[k];//继续往下找
	}
  }//for
  return head->count;
}//search
void del(Tire *root){//释放内存的函数
	for(int i=0;i<26;++i){
	  if(root->tire[i]!=NULL)
		  del(root->tire[i]);//递归寻找叶子结点
	  delete(root->tire[i]);//删除函数
	}//for
}//del
int main(){
	//freopen("1.txt","r",stdin);
  int num;
  char ss[22];
  init();
  scanf("%d",&num);
  for(int i=1;i<=num;++i){
    scanf("%s",ss);
	for(int j=0;j<strlen(ss);++j)
	  insert(ss+j,i);//插入字符串和字符串的序号,作为标记变量
  }//while
  int sum;
  char newss[22];
  scanf("%d",&sum);
  while(sum--){
    scanf("%s",newss);
	int x=search(newss);
	printf("%d\n",x);
  }//while
  del(a);
  return 0;
}//main


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值