例题4-1 古老的密码(Ancient Cipher, NEERC 2004, UVa1339)

    题目:给定两个长度相同且不超过100的字符串,判断是否能把其中一个字符串的各个字母重排,然后对26个字母做一个一一映射,使得两个字符串相同。例如,JWPUDJSTVP重排后可以得到WJDUPSJPVT,然后把每个字母映射到它前一个字母(B->A, C->B, ..., Z->Y, A->Z),得到VICTORIOUS。输入两个字符串,输出YES或者NO。

    分析:(这里只考虑str1作为待转换字符串和str2目标字符串(也可以两者角色不同),数组分为cnt1和cnt2)由于字母可以排序,我们就可以不用考虑字母的顺序。直接比较两个字符串各个字母出现的个数。将两个字符串进行排序后,用数组保存每个字母出现的次数。然后对两个数组进行比较。由于str1映射到str2,所以,在cnt1[1]与cnt2[0]比较,后面依次比较。


代码如下:
#include <stdio.h>
#include <string.h>
// 对字符串进行排序 
void sortStr(char str[])
{
	int i, j;
	char ch; 
	for (i=0; i<strlen(str)-1; i++) {
		for (j=0; j<strlen(str)-i-1; j++) {
			if (str[j]>str[j+1]) {
				ch = str[j];
				str[j] = str[j+1];
				str[j+1] = ch;
			}
		}
	}
}
// 计算字母出现的次数 
void calculate(int cnt[], char str[])
{
	int i;
	
	for (i=0; i<strlen(str); i++)
		cnt[str[i]-65]++;
}
// 判断是否可以转换 
int judge(int cnt1[], int cnt2[])
{
	int i, j, flag = 0;
	// cnt1[1]与cnt2[0]比较,后面依次比较 
	for (i=0, j=1; i<26; i++, j++) {
		if (j == 26) j = 0;
		if (cnt1[j] == cnt2[i]) flag++;
	}
	if (flag == 26) return 1; // 当flag=26,代表可以转换 
	return 0;
}

int main()
{
	char str1[100], str2[100];
	int cnt1[26] = {0}, cnt2[26] = {0};
	gets(str1);
	gets(str2);
	sortStr(str1);
	sortStr(str2);
	calculate(cnt1, str1);
	calculate(cnt2, str2);
	if (judge(cnt1, cnt2)) printf("Yes\n");
	else printf("No\n");
	return 0;
 } 


猜你喜欢

转载自blog.csdn.net/qq_38038143/article/details/79573649