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; }

 

  

转载于:https://www.cnblogs.com/fuzhihong0917/p/7617509.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值