解题思路:上下两个字符串,字符串1每个字符对应字符串2一个对应的字符,出现一对多或者多对一都错。
O(N)遍历,判断当前s1【i】是否有映射
有,就判断s2【i】是不是等于s1【i】对应的映射(是?一切安好:impossible)
没有,就映射s2【i】
这样只能判断是否有一对多,判断不了多对一
于是再搞一遍s2【i】对s1【i】的映射,要做的事情和上面一样。
然而你以为这样就对了吗?
本体坑点:如果你已经得出了25对映射且经过重重磨难把他们成功按顺序输出并且热泪盈眶的看到了正确的答案然后看到手掌颤抖提交喜提Wrong Answer事后才懊悔为什么不再思考一下我是不是已经可以得出第26对并把他们输出时,那么证明已经你已经看到题解并且有了想砍出题人的冲动。
上面缩句:25->26
下面是代码:(仍然觉得有两个数组可以不开,不过懒得改了)
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+5;
int ab[28],ba[28];
char s1[N],s2[N];
bool visa[28],visb[28];
int cnt;
int main()
{
scanf("%s %s",s1,s2);
int len = strlen(s1);
int flag = 1;
int cnt=0;
for (int i=0;i<len;i++){
//a-->b
if (ab[s1[i]-'a'+1]==0){
ab[s1[i]-'a'+1] = s2[i];
cnt++;
visa[s1[i]-'a'+1] = true;
}
else {
if (ab[s1[i]-'a'+1]!=s2[i]){
printf("Impossible\n");
flag=0;
break;
}
}
//b-->a
if (ba[s2[i]-'a'+1]==0){
ba[s2[i]-'a'+1] = s1[i];
visb[s2[i]-'a'+1] = true;
}
else {
if (ba[s2[i]-'a'+1]!=s1[i]){
printf("Impossible\n");
flag=0;
break;
}
}
}
if (flag){
if (cnt==25){
int atob,btoa;
for (int i=1;i<=26;i++){
if (visa[i]==false) atob = i;
if (visb[i]==false) btoa = i+96;
}
visa[atob] = true;
ab[atob] = btoa;
}
for (int i=1;i<=26;i++)
if (visa[i]) printf("%c->%c\n",i+96,ab[i]);
}
return 0;
}
水题++;