B3654 [语言月赛202208] 影子字符串

目录

题目背景

题目描述

输入格式

输出格式

输入输出样例

说明/提示

分析

思路+实践

结果

1.总代码

2、输出结果

题目背景

众所周知,影子并不是实际物体。

题目描述

给出多个字符串(数目未知),每行一个。

其中有可能会有重复的字符串,而我们认为在这些字符串中,较靠后出现的都是靠前出现的字符串的“影子”。

例如,

abc
def
abc
abc
abc

我们在第1,3,4,5 行都出现了字符串 abc,那么3,4,5 行的字符串会被称为“影子字符串”。

现在要求把所有的非影子字符串都按照行号从小到大依次拼接为一个长串并输出。

输入格式

多个字符串,每行一个,含义见题目描述。

注意:输入结尾以字符串 0 结束(即一行里仅有一个 0)。

输出格式

共一行,表示所有非影子字符串按照行号从小到大依次拼接成的一个长串。

输入输出样例

输入 #1

cc
b
a
cc
0

输出 #1

ccba

说明/提示

对于 20% 的数据,无重复字符串。

对于 100%的数据,1≤n≤500,字符串总长度不超过 50000 ,字符集为全部的小写字母、数字、 . 、! 和 &

也就是说,每个字符串中只包含小写字母、数字、 . 、! 和 &,不包含空格等特殊符号。

分析

1.根据题目描述中的:给出多个字符串(数目未知),每行一个。我们可以得出,这道题目需要用到二维字符数组,而数目未知告诉我们需要用的while(1)或者for(i=1;;i++),即无终止条件;

2.文中的“其中有可能会有重复的字符串,而我们认为在这些字符串中,较靠后出现的都是靠前出现的字符串的“影子”。”意思是指如果后面有的前面出现过了,那么后面出现的是影子,前面的我们仍然需要输出,即我们需要去重(去重:删去重复出现的):

举个例子:

abc//第1行
def//第2行
abc//第3行
abc//第4行
abc//第5行

 后面的3,4,5行都出现了第1行的内容,那么我们的输出只用输出第一行就行,3,4,5行不用输出;

3,文中对输出的要求是:“行号从小到大”,即我们这题不需要排序,只需要去重操作即可;

4,输入条件给了以下要求:

 注意:输入结尾以字符串 0 结束(即一行里仅有一个 0)。

什么意思呢?我们来看个例子:

如果我输入了一行:012334,那我应不应该结束呢?

答案当然是否定的,所以在结束时我们要加一个判断:‘0’的后面是否为‘\0’;

思路+实践

看完了分析,我们开始上手操作:

1、首先定义数组:

题目的最后的 说明/提示 限定了范围:

对于 100%100% 的数据,1≤n≤500,字符串总长度不超过50000 ,字符集为全部的小写字母、数字、 . 、! 和 &

那我们就照做:

#include<iostream>
using namespace std;
char a[505][50005];//题目规定总长为50000,最多有500个,为什么不是100行呢?
//我们取个极限值:就一行,还到了总长度,那就是50000。这个数组仅存非影子字符串
int main()
{
	char num[50005];//num:储存输入影子字符串
	int i=0,j;//i:有几组非影子字符串,j:循环条件
    return 0;
}

 2、开循环输入,然后设定填出循环的条件:

#include<iostream>
using namespace std;
char a[505][50005];
int main()
{
	char num[50005];
	int i=0,j;
	while(1)//不设定跳出循环条件
	{
		cin>>num;
		if(num[0]=='0'&&num[1]=='\0')//num是一个数组,不能判断是否为‘0’
        //加‘\0’的原因是满足一行仅存1个0
		{
			break;
		}
    return 0;
}

3、既然已经输入完了,我们就需要去重了

首先遍历之前输入的,如果发现就跳出循环,如果未存在就加入数组,当然发现需要一个标志,这里我用的flag:

#include<iostream>
#include<cstring>
using namespace std;
char a[505][50005];
int main()
{
	char num[50005];
	int i=0,j;
	while(1)
	{
		int flag=1;
		cin>>num;
		if(num[0]=='0'&&num[1]=='\0')
		{
			break;
		}
		for(j=i;j>=1;j--)//遍历数组
		{
			if(strcmp(a[j],num)==0)//判断是否相同,之后会出笔记讲一下4个常用的字符串函数
			{
				flag=0;
				break; 
			}
		}
		if(flag==1)
		{
			strcpy(a[++i],num);//复制num数组进a[++i]数组中
            //a[i++]:在a[i]存储,然后i+1;a[++i]:i先加1,然后存入数组
		}
	}
	return 0;
} 

4、去重结束后就可以输出,虽然文中说要拼接后输出,但我们一个一个输出达到的效果是一致的:

#include<iostream>
#include<cstring>
using namespace std;
char a[505][50005];
int main()
{
	char num[50005];
	int i=0,j;
	while(1)
	{
		int flag=1;
		cin>>num;
		if(num[0]=='0'&&num[1]=='\0')
		{
			break;
		}
		for(j=i;j>=1;j--)
		{
			if(strcmp(a[j],num)==0)
			{
				flag=0;
				break; 
			}
		}
		if(flag==1)
		{
			strcpy(a[++i],num);
		}
	}
	for(j=1;j<=i;j++)
	{
		cout<<a[j];
	}
	return 0;
} 

代码就实现了!

结果

1.总代码
#include<iostream>
#include<cstring>
using namespace std;
char a[505][50005];
int main()
{
	char num[50005];
	int i=0,j;
	while(1)
	{
		int flag=1;
		cin>>num;
		if(num[0]=='0'&&num[1]=='\0')
		{
			break;
		}
		for(j=i;j>=1;j--)
		{
			if(strcmp(a[j],num)==0)
			{
				flag=0;
				break; 
			}
		}
		if(flag==1)
		{
			strcpy(a[++i],num);
		}
	}
	for(j=1;j<=i;j++)
	{
		cout<<a[j];
	}
	return 0;
} 
2、输出结果

 感谢观看!还请各位官老爷们打个赏,Thanks♪(・ω・)ノ

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值