一、题目链接
http://noi.openjudge.cn/ch0107/11/
二、解题思路(Java)
三、解题思路(C++)
四、Java程序
import java.util.Scanner;
public class Main {
/**
* 判断26个大写字母是否全部出现在给定字符串中
*
* @param text String类型的对象,代表给定字符串
* @return 逻辑量,true当且仅当26个大写字母全部出现在text中,否则false
*/
public boolean containsAllUpperLetters(String text) {
char[] chars = text.toCharArray(); // 存储text中的每个字符
int[] occur = new int[128]; // 存储text中每个字符出现的次数
/* 利用foreach循环遍历获取text中的每个字符c */
for (char c : chars) {
occur[c]++; // 当前字符c出现的次数增加1次
}
/* 从大写字母A开始,到大写字母Z为止 */
for (char c = 'A'; c <= 'Z'; c++) {
if (occur[c] == 0) { // 如果有一个大写字母未出现
return false; // 则返回false
}
}
return true; // 以上没有返回false,说明26个大写字母全部出现,返回true
}
/**
* 判断加密信息和原信息之间是否存在字符唯一编码关系
*
* @param info String类型的对象,代表加密信息
* @param source String类型的对象,代表原信息
* @return 逻辑量,true当且仅当info和source之间存在字符唯一编码关系,否则false
*/
public boolean isSameCoded(String info, String source) {
int n = info.length();
char[] code = new char[128]; // 存放编码
boolean[] isCoded = new boolean[128]; // 标记字符是否已经编码,默认false
/* 从第一个字符开始,到最后一个字符为止 */
for (int i = 0; i < n; i++) {
if (!isCoded[info.charAt(i)]) { // 如果info的当前字符尚未编码
code[info.charAt(i)] = source.charAt(i); // 则用source的当前字符为其编码
isCoded[info.charAt(i)] = true; // 标记当前字符已经编码
}
else { // 否则,info的当前字符已经编码
if (code[info.charAt(i)] != source.charAt(i)) { // 如果这个编码不是source的当前字符
return false; // 则说明info和source之间唯一编码关系不成立,返回false
}
}
}
return true; // 以上没有返回false,说明info和source存在字符唯一编码关系,返回true
}
/**
* 根据给定的加密信息和原信息,对字符串进行解密
*
* @param info String类型的对象,代表给定的加密信息
* @param source String类型的对象,代表给定的原信息
* @param required String类型的对象,代表待解密的字符串
* @return String类型的对象,根据info和source的编码关系,对required进行解密
*/
public String decryption(String info, String source, String required) {
// 如果给定的加密信息和原信息不符合题目要求
if (!containsAllUpperLetters(source) || !isSameCoded(info, source)) {
return "Failed"; // 则返回Failed
}
int n = info.length();
int m = required.length();
char[] code = new char[128]; // 存放加密信息info与原信息source对应的编码
char[] ans = new char[m]; // 存放待解密的字符串required对应的所有解密字符
/* 从第一个字符开始,到最后一个字符为止 */
for (int i = 0; i < n; i++) {
code[info.charAt(i)] = source.charAt(i); // 利用原信息字符对加密信息字符进行编码
}
/* 从第一个字符开始,到最后一个字符为止 */
for (int i = 0; i < m; i++) {
ans[i] = code[required.charAt(i)]; // 利用编码表对required字符进行解密
}
return String.valueOf(ans);
}
public static void main(String[] args) {
Main test = new Main();
Scanner input = new Scanner(System.in);
String info = input.next();
String source = input.next();
String required = input.next();
System.out.print(test.decryption(info, source, required));
}
}
五、C++程序
#include <iostream>
using namespace std;
int main()
{
string info; // 小C掌握的一条加密信息
string source; // info对应的原信息
string required; // 待解密的信息
cin >> info;
cin >> source;
cin >> required;
int m = source.length(); // 加密信息info和原信息source的长度
int n = required.length(); // 待解密的信息required的长度
char ans[n]; // 对required解密后形成的信息
char code[128] = {'\0'}; // 存放info和source字符对应的编码,初始时均为'\0'
int occur[128] = {0}; // 存储source中每个字符出现的次数,初始时均为0
/* 利用foreach循环遍历获取source中的每个字符c */
for (char c: source)
{
occur[c]++; // 当前字符c出现的次数增加1次
}
/* 从大写字母A开始,到大写字母Z为止 */
for (char c = 'A'; c <= 'Z'; c++)
{
if (occur[c] == 0) // 如果有一个大写字母在source中未出现
{
cout << "Failed"; // 则说明source不符合要求,输出Failed
return 0; // 直接退出程序
}
}
/* 从第一个字符开始,到最后一个字符为止 */
for (int i = 0; i < m; i++)
{
if (code[info[i]] == '\0') // 如果当前info的字符尚未编码
{
code[info[i]] = source[i]; // 则通过对应的source字符为其编码
}
else // 否则,当前info的字符已经编码
{
if (code[info[i]] != source[i]) // 如果该编码不是对应的source字符
{
cout << "Failed"; // 则说明info和source之间唯一编码关系不成立,输出Failed
return 0; // 直接退出程序
}
}
}
/* 以上均为退出程序,说明可以正常解密 */
for (int i = 0; i < n; i++)
{
ans[i] = code[required[i]]; // 通过编码表对required各字符进行解密
cout << ans[i]; // 输出解密后的字符
}
return 0;
}