HDU2532 Engine(AC)

Engine

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 772    Accepted Submission(s): 172


Problem Description
谷歌、百度等搜索引擎已经成为了互连网中不可或缺的一部分。在本题中,你的任务也是设计一个搜索论文的搜索引擎,当然,本题的要求比起实际的需求要少了许多。
本题的输入将首先给出一系列的论文,对于每篇论文首先给出标题,然后给出它被引用的次数。然后会有一系列的搜索询问,询问标题中包含特定关键词的论文有哪些。
每一个询问可能包含多个关键词,你需要找出标题包含所有关键词的论文。
“包含”必须是标题中有一个词正好是给定的关键词,不区分大小写。
对每个询问,都按被引用的次数从多到少输出满足条件的论文的标题。如果有被引用的次数相同的论文,则按照论文在输入中的顺序排列,先给出的论文排在前面。

 

Input
输入包含多组数据。
每组数据首先有一行包含一个整数N(1<=N<=1000),表示论文的数目,N=0表示输入结束。每组论文的信息第一行是论文的标题,由字母(大小写均可)和空格组成,不超过10个词,每个词不超过20个字符,标题总共不超过250个字符。第二行是一个整数K(0<=K<=108),表示它被引用的次数。在论文信息结束以后,有一行包含一个整数M(1<=M<=100),表示询问的数目。接下来有M行,每行是一个询问,由L(1<=L<=10)个空格分开的词构成,每个词不超过20个字符。

 

Output
对每个询问,按照题目给定的顺序输出满足条件的论文的标题;如果没有满足条件的论文,就不输出。在每组询问的输出之后输出一行”***”,在每组数据的输出之后输出一行”---”。
 

Sample Input
  
  
6 Finding the Shortest Path 120 Finding the k Shortest Path 80 Find Augmenting Path in General Graph 80 Matching in Bipartite Graph 200 Finding kth Shortest Path 50 Graph Theory and its Applications 40 6 shortest path k shortest path graph path find application 0
 

Sample Output
  
  
Finding the Shortest Path Finding the k Shortest Path Finding kth Shortest Path *** Finding the k Shortest Path *** Matching in Bipartite Graph Find Augmenting Path in General Graph Graph Theory and its Applications *** Finding the Shortest Path Finding the k Shortest Path Find Augmenting Path in General Graph Finding kth Shortest Path *** Find Augmenting Path in General Graph *** *** ---
//搜索之后才知道这也是个模拟题,自己认为怎么也是和字符
//串查找有关系
//第一次WA
//输入有问题,要while,第二次还是WA,额,继续查错
//最后发现错误竟然是是在strcmpp()函数里没有把s2改成小写字母,只是把s1改成小写字母,好吧,查了很久,就是找不到问题,后来一句句看才发现。。。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#define MAXN 1005
#define MAXS 255
#define MAXG 11
#define MAXL 21

typedef struct headlines
{
	char stringwen[MAXS]; //最多10个词,整个长度最长不超过250
	int  yiyongnum;
	int  index;
	char singlestr[MAXG][MAXL];
	int  len;
}headline;


headline filewen[MAXN];
headline searchwen;

int tc = 0;


void init()
{
	int i = 0;
	int j = 0;
	int m = 0;
	int n = 0;
	for (i = 0; i < MAXN;i++)
	{
		for (j = 0; j < MAXS;j++)
		{
			filewen[i].stringwen[j] = '\0';
		}
		filewen[i].yiyongnum = 0;
		filewen[i].index     = 0;
		filewen[i].len       = 0;
		for (m = 0; m < MAXG; m++)
		{
			for (n = 0; n < MAXL; n++)
			{
				filewen[i].singlestr[m][n] = '\0';
			}
		}
	}
	return;
}

void initquery()
{
	int j = 0;
	int m = 0;
	int n = 0;
	for (j = 0; j < MAXS; j++)
	{
		searchwen.stringwen[j] = '\0';
	}
	searchwen.len = 0;
	for (m = 0; m < MAXG; m++)
	{
		for (n = 0; n < MAXL; n++)
		{
			searchwen.singlestr[m][n] = '\0';
		}
	}
	return;
}

int strlength(char *str)
{
	int size = 0;
	while ('\0' != *str)
	{
		size += 1;
		str++;
	}
	return size;
}

void parse(headline* input)
{
	int i = 0;
	int len = strlength(input->stringwen);
	int num = 0;
	int sinleindex = 0;
	int spaceflag = 0;

	for (i = 0; i < len; i++)
	{
		//不能让空格进来,也不能让空字符串过来
		if ((' ' == input->stringwen[i]) || ('\0' == input->stringwen[i]))
		{
			spaceflag = 1;
			continue;//空格直接过滤
		}

		//什么情况下需要转到下一行
		if ((1 == spaceflag) && (0 != sinleindex))//如果第一个就是空格,肯定要去掉这个空格
		{
			//那就是之前已经保存了一些字符,然后遇到了空格
			input->singlestr[num][sinleindex] = '\0';

			num += 1;
			sinleindex = 0;
		}
		spaceflag = 0;
		input->singlestr[num][sinleindex] = input->stringwen[i];
		sinleindex += 1;
	}
	input->len = num + 1;
	return;
}

int cmp(headline check1, headline check2)
{
	if (check1.yiyongnum > check2.yiyongnum)
	{
		return 1;
	}
	else if (check1.yiyongnum == check2.yiyongnum)
	{
		if (check1.index > check2.index)
		{
			return -1;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return -1;
	}
}

//这样就是从大到小排序,也可以吧,cmp一定要注意啊,就是这么写的
void paixu(headline *str, int start , int end)
{
	int i = start;
	int j = end;
	//char tmp[MAXS];
	int m = 0;
	/*for (m = 0; m < str[start].len;m++)
	{
		tmp[m] = str[start].stringwen[m];   
	}*/
	headline tmp;
	tmp = str[start];
	 
	//先用引用数作为关键字排序,然后再用序号作为第二关键字来排序
	//排序还是用快排来做
	if (start > end) return;
	while (i<j)
	{
		//先从右往左找,右边的数总是大的
		while ((i < j) && (cmp(str[j], tmp) <=0))
		{
			j--;
		}
		str[i] = str[j];
		while ((i < j) && (cmp(str[i], tmp)>=0))
		{
			i++;
		}
		str[j] = str[i];
	}
	str[i] = tmp;
	paixu(str, start, i-1);
	paixu(str, i+1, end); //不能写i
	return;
}

int strcmpp(char* s1, char* s2)
{
	while (s1 && s2 && ('\0' != *s1) && ('\0' != *s2))
	{
		//先弄下大小写
		if ((*s1 >= 'A') && (*s1 <= 'Z'))
		{
			*s1 += ('a' - 'A'); //这个要注意,自己一开始写错了
		}
		
		if ((*s2 >= 'A') && (*s2 <= 'Z'))
		{
			*s2 += ('a' - 'A'); //这个要注意,自己一开始写错了
		}
		if (*s1 != *s2) return 0;
		s1++;
		s2++;
	}
	return 1;
}

int find(int fileindex, int searchindex)
{
	int i = 0;
	int len1 = 0;
	int len2 = strlength(searchwen.singlestr[searchindex]);


	for (i = 0; i < filewen[fileindex].len; i++)
	{
		len1 = strlength(filewen[fileindex].singlestr[i]);
		if (len1 != len2) continue;
		if (1 == strcmpp(filewen[fileindex].singlestr[i], searchwen.singlestr[searchindex]))
		{
			return 1;
		}
	}

	return 0;
}

void getans()
{
	int i = 0;
	int j = 0;
	int findflag = 1;
	for (i = 1; i <= tc;i++)
	{
		findflag = 1;
		//在第一条论文里比较查询的单词
		for (j = 0; j < searchwen.len;j++)
		{
			if (0 == find(i, j))
			{
				findflag = 0;
				break;//说明这条没找到,那下面的就不用找了
			}
		}
		if (1 == findflag)
		{
			//如果都找到了,就输出
			printf("%s\n", filewen[i].stringwen);
		}
	}
	return;
}

int main()
{
	int checknum = 0;
	int i = 0;
	freopen("input.txt","r",stdin);
	while ((1 == scanf("%d", &tc))&& (0 != tc))
	{
		init();
		for (i = 1; i <= tc; i++)
		{
			getchar();
			gets(filewen[i].stringwen); //之前没管那个\n就这一直gets不到字符串
			scanf("%d", &filewen[i].yiyongnum);
			filewen[i].index = i;//因为后面需要排序,所以这个序列号也要存着
			if (7 == i)
			{
				tc = tc;
			}
			parse(&filewen[i]);
			//getchar();
		}

		paixu(filewen, 1, tc); //开始排序了,用快排

		scanf("%d", &checknum);
		getchar();
		for (i = 1; i <= checknum; i++)
		{
			initquery();
			gets(searchwen.stringwen);
			//分解
			parse(&searchwen);
			getans();
			printf("***\n");
		}
		printf("---\n");
	}
	return 0;
}




 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值