1029 旧键盘 (20 分)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
思路1:
Encrypt函数用来除去key字符串中重复的字符,并存入keych中,main函数中count记录要存入str3数组元素的个数,while循环采用双指针遍历两个字符串,若两指针指向的元素不同,则将str1指针指向的元素的大写存入str3数组中,否则指针同时后移。while循环结束后,str1字符串必定还未遍历完,应该继续处理,将剩余元素改成大写存入str3中,最后调用Encrypt函数进行去重存放在str4中,最后输出str4即可。
参考代码1:
#include <iostream>
#include <cstring>
using namespace std;
void Encrypt(char* keych,char *key){//除去key字符串重复的字符,并存入keych中;
keych[0]=key[0];//初始化首字符;
int j=0,flag;//j代表keych数组即将存放的下标;
for(int i=0;i<strlen(key);i++){//遍历key数组;
flag=1;
//判断key[i]是否与keych中的某个字符相等,如果有相等的字符,则将flag置为0;
for(int k=0;k<j+1;k++){//遍历keych数组中以存储的每一个元素;
if(key[i]==keych[k])
flag=0;
}
if(flag){//若flag=1,则说明keych[0-j]中不存在与key[i]相同的字符,那就将这个元素存放在keych数组的j+1位置。
j=j+1;
keych[j]=key[i];
}
}
keych[j+1]='\0';//处理结尾;
}
int main(){
string str1,str2;//str1应该被输入的字符串,str2实际被输入的字符串;
cin>>str1>>str2;
int i,j=0;
char str3[100],str4[100];
int count=0;
while(str1[i]!=NULL&&str2[j]!=NULL){//双指针遍历;
if(str1[i]!=str2[j]){//若两指针指向的字符不同则输出第一个字符串指针对应字符;
if(islower(str1[i])){//若是小写改成大写存入待去重数组str3;
str3[count]=toupper(str1[i]);//
}
else {
str3[count]=str1[i];
}
i++;
count++;
}
else {//若相同则指针同时后移;
i++;
j++;
}
}
if(str2[j]==NULL){//处理str1剩余部分,(很有可能这些字符,str2都没有);
for (int k=i;k<str1.length();k++) {
if(islower(str1[k])){//若是小写改成大写存入待去重数组str3;
str3[count]=toupper(str1[k]);//
}
else {
str3[count]=str1[k];
}
count++;
}
}
Encrypt(str4,str3);
cout<<str4;
return 0;
}
思路2:
用HashTable来标记某一字符是否被输出,外层for循环遍历str1的每一个元素,内层for循环遍历str2的每一个元素并用c1,c2临时存放当前遍历元素,若是小写则改写为大写。在遍历中若c1与c2相同即c1在第二个字符串中出现过,则结束内层循环。若内层循环正常结束,且c1还未被输出过,则输出c1,再将HashTable[c1]置为true表示已输出。程序继续执行,知道外层循环也结束,则输出完毕。
参考代码2:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main(){
string str1,str2;
bool HashTable[128]={false};//HashTable数组用来标记字符是否已被输出;
cin>>str1>>str2;
int len1=str1.length(),len2=str2.length();
for(int i=0;i<len1;i++){
int j;
char c1,c2;
for(j=0;j<len2;j++){
c1=str1[i];
c2=str2[j];
if(c1>='a'&c1<='z') c1-=32;//若是小写字母,则转换为大写;
if(c2>='a'&c2<='z') c2-=32;
if(c1==c2) break;//若c1在第二个字符串中出现,则跳出。
}
if(j==len2&&HashTable[c1]==false){
printf("%c",c1);//在第二个字符串中未出现c1,且c1未输出过;
HashTable[c1]=true;
}
}
return 0;
}
点评:
①此题属于散列型,在要求不重复输出数据时经常使用,采用bool型数组HashTable可以实现空间换时间的时间复杂度简化。
②思路1是野路子,Encrypt函数可以去除字符串中重复的字符,可达到题目的输出要求。而思路2则是此类问题的标准解法,需要充分理解并熟练掌握。
③参考代码1中涉及到许多函数例如isupper(),toupper(),tolower.(),用以解决大小写转换问题,也可采用参考代码2中的c2-=32,需对ASCII码有一定的了解。