ZZULIOJ 2855: 小A的恰饭系列

题目描述

小A、小B、小C三同学一起去餐厅恰饭,他们拿起菜单不知道该点什么菜好,小A提出建议:我们每人说一个字符,菜品名称中同时含有我们说的字母时,我们就点这个菜。
此时小B意识到如果这种方式点菜会有点多,三人吃不完,提出建议:我们三人给出的字符按小A、小B、小C的顺序组成一个字符串s,如果这个字符串s是菜品名称中的一个子序列时,我们就点它。
小C发现,按这个规则点菜,最后点的菜还是有很多,吃不完,提出建议:菜品名称中至少含有三个子序列是字符串s时,我们才点它,我们认为两个子序列不同是他们的下标不完全相同。
子序列的定义:存在任意下标a < b < c,那么“p[a]p[b]p[c]”就构成字符串p的一个子序列。如“ABC”的子序列有“A”、“B”、“C”、“AB”、“AC”、“BC”、“ABC”。

输入

第一行输入三个字符,分表代表小A,小B,小C三人给出的字符。(数据保证三人给出的字符不同)
第二行输入一个整数N,代表菜品的个数。 1<=N<=1000
接下来输入N行,每行一串字符,代表菜品的名称。所有字符都是大写。每行字符长度小于100。

输出

输出被选中的菜品名称。如果没有菜品被选中,请输出“Don't eat for all the trouble”

样例输入

O I N
5
GONGBAOJIDING
HONGSHAOPAIGU
DONGPOROU
XIANGGUHE
HONGSHAONIUROUMIAN

样例输出

GONGBAOJIDING
HONGSHAONIUROUMIAN

思路

就是找子序列个数,但是暴力可能超时,但我们注意到长度为三,这时就可以取巧,拿样例举例;中间的是I,左边是O,右边是N;设有x个I,只需知道每一个I的前面有几个O(a个)和后面有几个N(b个);就能知道这个含有这个I的子序列有a*b个,再将其相加,得子序列数;

注意:不要每次使用前面有几个O(a个)和后面有几个N(b个)时就遍历一边字符串,浪费时间,建议打表;

代码

#include<stdio.h>
#include<string.h>
int main()
{
	int a,b,c,d,e,f;
	char a1,b1,c1;
	scanf("%c %c %c",&a1,&b1,&c1);
	scanf("%d ",&a);
	int x[a],y[105]; //y[105]相当于打表,用于记录相应位置前面有几个a1
	char z[a][105];
	f=0;
	for(b=0;b<a;b++)
	{
		d=e=0;
		gets(z[b]);
		if(z[b][0]==a1)
		y[0]=1;
		else
		y[0]=0;
		for(c=1;c<strlen(z[b]);c++)
		{
			if(z[b][c]==a1)
			y[c]=y[c-1]+1;
			else
			y[c]=y[c-1];
		}
		for(c=strlen(z[b])-1;c>=0;c--)
		{
			if(z[b][c]==c1)
			e++;
			else if(z[b][c]==b1)
			d=d+e*y[c];
		}
		if(d>=3)
	    x[f++]=b; //将对应下标存入数组,方便最后输出
	}
	if(f==0)
	printf("Don't eat for all the trouble\n");
	else
	{
		for(c=0;c<f;c++)
		puts(z[x[c]]);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值