CFGym 100211J 题解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CFGym 100211J 题解相关的知识,希望对你有一定的参考价值。
一、题目
二、题意
给定一个字母表(最多也就是英文小写字母的前10个字母),一个交换表,两个字符串,判断字符串A能否通过交换表的交换方式变成字符串B。
三、思路
1、一开始,比赛时,我半模拟半记忆化地做,越做越糊涂,越做越复杂,最后直到比赛结束也没有做出来。T_T实力还是有很大地提升空间啊。
2、比赛后,问了过了的队伍,秒懂,此法实在是妙啊。因为交换表中最多也只有45种交换,那么,可以枚举交换表中没有的交换关系,假设为两个字符为ab,那么,保留串A和串B中的所有a和b(即去掉非a且非b的元素),判断剩余的两个串是否相等,不想等则可以输出NO。因为如果你要把串A变成串B,就必须对串A的剩余串做元素位置交换,而交换表中不存在这种交换,所以,串A是无法变成串B的。最后,如果前面一直没有输出NO,则输出YES。就是这么简单。。。。。。诶,最近脑子比较进水啊。坚持下去,你就是最棒的!
四、注意事项
1、题目中没说两个串一定相等,虽然可能所有测试样例都是长度相等的,但为了保险起见,还是判断一下好。
2、题目中没说两个串含有的字符数量是相等的,即可能存在这样的样例:串A:abbbba,串B:bbbbba。这种情况也要判断一下。
3、交换表中的交换关系是可以的对换的。即如果存在交换ab,那么,ba也是存在的。
4、输入输出是要重定向到文件的。别被坑了。
五、源代码
#include<bits/stdc++.h>
using namespace std;
int n, m;
bool mp[20][20];
char str[2][100010];
int cnt[2][30];
int len[2];
string s[2];
bool test(char a, char b) {
for(int i = 0; i < 2; ++i) {
s[i].clear();
for(int j = 0; j < len[i]; ++j)
if(str[i][j] == a || str[i][j] == b)s[i] += str[i][j];
}
return s[0] == s[1];
}
int main() {
freopen("traces.in", "r", stdin);
freopen("traces.out", "w", stdout);
char temp[4];
while(~scanf("%d%d", &n, &m)) {
memset(mp, 0, sizeof(mp));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < m; ++i) {
scanf("%s", temp);
mp[temp[0] - ‘a‘][temp[1] - ‘a‘] = mp[temp[1] - ‘a‘][temp[0] - ‘a‘] = true;
}
scanf("%s", str[0]);
scanf("%s", str[1]);
len[0] = strlen(str[0]), len[1] = strlen(str[1]);
bool flag = true;
for(int i = 0;i < 2;++i){
for(int j = 0;j < len[i];++j){
++cnt[i][str[i][j] - ‘a‘];
}
}
for(int i = ‘a‘;i < ‘a‘ + n;++i)
if(cnt[0][i - ‘a‘] != cnt[1][i - ‘a‘])flag = false;
for(int i = ‘a‘;flag && i < ‘a‘ + n; ++i) {
for(int j = i + 1; j < ‘a‘ + n; ++j) {
if(!mp[i - ‘a‘][j - ‘a‘]) {
if(!test((char)i, (char)j)) {
i = ‘a‘ + n;
flag = false;
break;
}
}
}
}
printf("%s\\n", flag ? "YES" : "NO");
}
return 0;
}
以上是关于CFGym 100211J 题解的主要内容,如果未能解决你的问题,请参考以下文章