1029 旧键盘 (20 分)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _
(代表空格)组成。题目保证 2 个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
解题思路:
- 可以很容易地想到用散列的思想解决问题。比较直接的想法是:构建一个bool型的hash数组,在读入第二个字符串时,用该数组记录某字符是否出现过,再枚举第一个字符串,若当前枚举到的字符在hash数组中的值为false,则说明该字符对应的键盘是坏的,并输出该字符。
- 但以上的想法需要解决三个问题。其一,在题目要求读入的字母不区分大小写的情况下如何准确记录字符出现的情况;其二,在输出字母时只输出为大写字母的形式;其三,每个符合要求的字符只输出一次。
- 第一个问题的解决方式:在change函数的编写上作出适当改动,以便将同一个字母的大小写形式均对应到hash数组的同一单元,相应代码如下:
int change(char c) { if(c>='0'&&c<='9')return c-'0'; if(c>='a'&&c<='z')return (c-32)-'a'+10;//c-32是为了将小写字母转换为大写形式 if(c>='A'&&c<='z')return c-'A'+10; if(c=='_')return 37; }
- 第二个问题解决方式:在扫描到符合输出要求的字符时,如果该字符为小写字母,则转换为大写形式输出,具体转换方式见3
第三个问题解决方式:把hash数组定义为结构体数组,每个单元包含两个变量,一个bool型变量记录当前字符是否已输出过,另一个int型变量用于记录该字符是否在第二个字符串中出现过。结构体定义如下:
struct hash
{
bool flag;
int a;
}hashT[maxn];
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100;
struct Hash
{
bool flag;
int a;
}hashT[128];
int change(char c)
{
if(c>='0'&&c<='9')return c-'0';
if(c>='a'&&c<='z')return c-32-'a'+10;
if(c>='A'&&c<='Z')return c-'A'+10;
if(c=='_')return 37;
}
int main()
{
char str1[maxn],str2[maxn];
cin.getline(str1,maxn);
cin.getline(str2,maxn);
int len1=strlen(str1);
int len2=strlen(str2);
for(int i=0;i<128;++i)//对hashT数组进行初始化
{
hashT[i].flag=false;
hashT[i].a=0;
}
for(int i=0;i<len2;++i)
{
hashT[change(str2[i])].a++;
}
for(int i=0;i<len1;++i)
{
if(hashT[change(str1[i])].a==0&&hashT[change(str1[i])].flag==false)
{
hashT[change(str1[i])].flag=true;
if(str1[i]>='a'&&str1[i]<='z')printf("%c",str1[i]-32);
else printf("%c",str1[i]);
}
}
return 0;
}
Atalanta
2019.2.22