牛客21805 字符串编码与解码(模拟+枚举)

链接:https://ac.nowcoder.com/acm/problem/21805
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给你两个长度相同的字符串a,b,现在已知b是a编码之后的结果
比如a = "CAT", b = "DOG", 那么D其实是C,O其实是A,G其实是T

现在给你一个字符串c,如果c能够被解码出来,输出c解码后的字符串,如果不能输出@

输入描述:

输入三行,每行一个字符串,长度在50以内

输出描述:

输出一个字符串

示例1

输入

复制

CAT
DOG
GOD

输出

复制

TAC

示例2

输入

复制

BANANA
METETE
TEMP

输出

复制

@

示例3

输入

复制

THEQUICKBROWNFOXJUMPSOVERTHELAZYHOG
UIFRVJDLCSPXOGPYKVNQTPWFSUIFMBAZIPH
DIDYOUNOTICESKIPPEDLETTER

输出

复制

CHCXNTMNSHBDRJHOODCKDSSDQ

备注:

子任务1:|a| <= 10
子任务2:|a| <= 40
子任务3:无限制

分析:我们由字符串a和b的一一对应关系,可以推出每个字母对应的的破解字母,例如给你两个长度相同的字符串a,b,现在已知b是a编码之后的结果
比如a = "CAT", b = "DOG", 那么D其实是C,O其实是A,G其实是T。依据“一一对应”原则可以知道,每个字母只能对应一个破解字母。如果对应多个,那么这肯定是无法破解的。我们可以先统计字符串B中每个字母出现次数,再统计字符串A中每个字母出现次数,由次数从小到大进行排序,检查从A到Z每个stra[i]是否等于strb[i],只要有一个不等于,那么这肯定是不合法的无法破解,直接输出@即可。

       如果合法的话,我们再看待破解的字符串中每个字符是否都能在字符串B中找到。那么这个字符串就可以破解了,如果有找不到的,我们还要再分情况讨论。如果在字符串B中能找到25个不同的字母的破解字母,我们就可以推测出剩下一个未出现字母的破解字母,这也是样例3给我们的提示,这样我们同样能够对待破解字符串进行破解,剩下的情况就无法破解了。比如有两个找不到的字母我们就无法推出其中一个字母的破解字母是谁。

#include<stdio.h>
#include<string.h>
typedef long long ll;
const int M=2e2+5;
char stra[M],strb[M],str[M];
ll i,j,k,size1,size2,STA[M],STB[M],sum=0,ta=0,tb=0,t=0;
void mysort(ll *a,ll n);//定义冒泡排序,本来想用sort排序,但总是被WA掉,只好用这个了
int main()
{
    scanf("%s",stra);//输入字符串A
    scanf("%s",strb);//输入字符串B
    size1=strlen(stra);
    for(i=0;i<size1;i++)//统计26个字母在字符串A和字符串B中每个字母出现的次数
    {
        STA[stra[i]]++;STB[strb[i]]++;
    }
    for(i='A';i<='Z';i++)//统计26个字母有多少个在字符串B中出现过
    {
        if(STB[i]!=0)
        sum++;
    }
    if(sum==25)//如果只有一个字母没有出现过,我们同样可以推测出没出现的字母和对应的破解字母
    {
        for(i='A';i<='Z';i++)
        {
            if(STA[i]==0)
                ta=i;
            if(STB[i]==0)
                tb=i;
        }
    }
    scanf("%s",str);
    size2=strlen(str);
    mysort(STA,91);
    mysort(STB,91);
    for(i='A';i<='Z';i++)
    {
        if(STA[i]!=STB[i])//检查字符串B与字符串A中字母是否一一对应
        {
            printf("@\n");//只要有一组不对应就直接输出@结束
            return 0;
        }
    }
    for(j=0;j<size2;j++)
    {
        for(i=0;i<size1;i++)
        {
            if(strb[i]==str[j])//检查待破解字符串中每个字母是否在字符串B中能找到
            {
                t++;
                break;
            }
        }
    }
    if(t==size2)//如果都能找到,就进行一一对应破解
    {
        for(j=0;j<size2;j++)
            for(i=0;i<size1;i++)
            {
                if(strb[i]==str[j])
                {
                    str[j]=stra[i];
                    break;
                }
            }
    }
    else if(sum==25)//如果有找不到的但是能通过已破解的25个字母推测出剩下一个字母,那么也可以
    {                                     //进行破解
        for(j=0;j<size2;j++)
            for(i=0;i<size1;i++)
            {
                if(strb[i]==str[j])
                {
                    str[j]=stra[i];
                    break;
                }
                else if(str[j]==tb)
                {
                    str[j]=ta;
                    break;
                }
            }
    }
    else//剩下情况就无法破解了直接输出@结束即可
    {
         printf("@\n");
            return 0;
    }
    for(i=0;i<size2;i++)//输出破解后的字符串
    {
        printf("%c",str[i]);
    }
    printf("\n");
}
void mysort(ll *a,ll n)//定义冒泡排序函数
{
    int t;
    for (int j=0;j<n-1;j++)
    {
        for (int i=0;i<n-j-1;i++)
        {
            if(a[i]>a[i+1])
            {
                t=a[i];
                a[i]=a[i+1];
                a[i+1]=t;
            }
        }
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值