CSUOJ:1226: ACM小组的内战

Description
ACM小组最近开始出现一些内部矛盾,主要原因是Samsara,Sowicm与Gestapolur对小组的命名产生了分歧,但是Samsara和 Sowicm是绝对不会屈服于Gestapolur,所以他们暗中联系怎样打败Gestapolur,但是为了不让Gestapolur发现他们的目的, 他们希望会编程的你用他们的规则对信息进行加密,以利于他们更完美的战胜Gestapolur。

Input
输入包含约100组数据,每组数据包括四行,第一行和第二行有两个长度相同的字符串S1和S2,分别表示明文到密文的对应关系,第一行为明文字符串S1, 第二行为对应加密关系字符串S2,第三行为需要加密的明文字符串S3,第四行为需要解密的密文字符串S4。 (1<=length(S1)=length(S2),length(S3),length(S4)<255)
读入以EOF结束。

Output
每组数据输出两行,每组第一行输出S3对应的密文字符串,第二行输出S4对应的明文字符串,对每一行输出,如果出现未给出的明文到密文的对应关系或者对应关系有误(一个明文对应多个密文或多个明文对应一个密文)就输出“Wrong”(不包括引号)。

Sample Input

abcde
fghij
anc
fhi

Sample Output

Wrong
acd

Hint
数据中给出所有字符串只包含数字及大小写字母。

Source
CSU Monthly 2011 Dec.

AC代码:

#include<iostream>
#include<string>
#include<cstring>

using namespace std;

int main()
{
    bool flag1[300], flag2[300];
    string s1, s2, s3, s4, a1, a2;
    while (cin >> s1 >> s2 >> s3 >> s4)
    {
        memset(flag1, 0, sizeof flag1);
        memset(flag2, 0, sizeof flag2);

        for (string::size_type i = 0; i != s1.size(); i++)
        {
            if (s1.find(s1[i]) != s1.rfind(s1[i]))//判断s1中是否有重复字符
                if (s2[s1.find(s1[i])] != s2[s1.rfind(s1[i])])
                    flag1[i] = true;
            if (s2.find(s2[i]) != s2.rfind(s2[i]))//判断s2中是否有重复字符
                if (s1[s2.find(s2[i])] != s1[s2.rfind(s2[i])])
                    flag2[i] = true;
        }

        for (string::size_type i = 0; i != s3.size(); i++)
        {
            if (s1.find(s3[i]) != string::npos && !flag1[s1.find(s3[i])])
                a1.push_back(s2[s1.find(s3[i])]);
            else
            {
                a1 = "Wrong";
                break;
            }
        }

        for (string::size_type i = 0; i != s4.size(); i++)
        {
            if (s2.find(s4[i]) != string::npos && !flag2[s2.find(s4[i])])
                a2.push_back(s1[s2.find(s4[i])]);
            else
            {
                a2 = "Wrong";
                break;
            }
        }

        cout << a1 << endl;
        cout << a2 << endl;
        a1.clear();
        a2.clear();
    }
    return 0;
}

思路分析:
用四个string存四个输入,两个bool数组分别处理明文和密文中的重复字符。
两个输出实际上是等价的,能解决第一个输出,第二个输出也能采用同样的方法。
以找出s3对应的输出为例:
通过string的find函数和rfind函数来判断s1的当前字符是否有重复。如果重复,两函数返回的索引值必然是不相等的。然后判断s2在两个索引值的字符是否相同,如果不同,说明是“真的”出现了一对多的情况,对该字符进行标记。
在求s3对应的输出a1时,先用find函数判断当前s3中的字符是否存在于s1中,且是否被标记。如果存在且未被标记就将s2中对应位置的字符存入a1中。只要任一条件不满足,a1即为Wrong。
s2和s4同理。

这题一开始分析的不是很清楚,主要是这段话:

对每一行输出,如果出现未给出的明文到密文的对应关系或者对应关系有误(一个明文对应多个密文或多个明文对应一个密文)就输出“Wrong”(不包括引号)。

一开始的想法是只要s1中出现重复字符s3对应的输出就给Wrong,s2、s4同理。交完果断WA了。之后想只要s3中出现的字符在s1中不重复,就能输出对应密文,s2、s4同理。依然是WA。交到怀疑人生后拿别人的AC代码测试了一遍终于发现了隐藏的问题:即使s3中出现了s1里的重复字符,也有可能不输出Wrong。只要重复字符对应的密文也是相同的即可,例如dd对ii。

估计我还需要重新学学语文Orz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值