古老的密码

古老的密码(Ancient Cipher, NEERC 2004, UVa1339)
给定两个长度相同且不超过100的字符串,判断是否能把其中一个字符串的各个字母重
排,然后对26个字母做一个一一映射,使得两个字符串相同。例如,JWPUDJSTVP重排后可
以得到WJDUPSJPVT,然后把每个字母映射到它前一个字母(B->A, C->B, …, Z->Y, A-
>Z),得到VICTORIOUS。输入两个字符串,输出YES或者NO。
【分析】
既然字母可以重排,则每个字母的位置并不重要,重要的是每个字母出现的次数。这样
可以先统计出两个字符串中各个字母出现的次数,得到两个数组cnt1[26]和cnt2[26]。下一步
需要一点想象力:只要两个数组排序之后的结果相同,输入的两个串就可以通过重排和一一
映射变得相同。这样,问题的核心就是排序。
C语言的stdlib.h中有一个叫qsort的库函数,实现了著名的快速排序算法。它的声明是这
样的:
void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void *
) );
前3个参数不难理解,分别是待排序的数组起始地址、元素个数和每个元素的大小。最
后一个参数比较特别,是一个指向函数的指针,该函数应当具有这样的形式:
int cmp(const void *, const void *) { … }
这里的新内容是指向常数的“万能”的指针:const void *,它可以通过强制类型转化变成
任意类型的指针。对于本题来说,排序的对象是整型数组,因此要这样写:
int cmp ( const void *a , const void *b ) {
return *(int *)a - *(int *)b;
}
一般地,需要先把参数a和b转化为真实的类型,然后让cmp函数当a<b、a=b和a>b时分别
返回负数、0和正数即可。学会排序之后,本题的主程序并不难编写,读者不妨一试。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define maxn 110
char s1[maxn], s2[maxn];
int a1[27], a2[27],len,i,flag,t;
int cmp ( const void *a , const void *b ) {
return *(int *)a - *(int *)b;
}
int main()
{
 while (scanf("%s%s", s1, s2)!=EOF) {
  len = strlen(s1);
  flag = 1;
  memset(a1, 0, sizeof(a1));
  memset(a2, 0, sizeof(a2));
  for (i = 0;i < len;i++) {
   a1[s1[i] - 'A']++;
   a2[s2[i] - 'A']++;
  }
 qsort(a1,26,sizeof(a1[0]),cmp);
    qsort(a2,26,sizeof(a2[0]),cmp);
  for (i = 0;i < 26;i++)
   if (a1[i] != a2[i]) {
    flag = 0;
    break;
   }
  if (flag) printf("YES\n");
  else printf("NO\n");

 }
 return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值