题目:古老的密码(Ancinet Cipher,NEERC 2004,UVa1339)
给定两个长度相同且不超过100的字符串,判断是否能把其中一个字符串的各个字母重排,然后对26个字母做一个一一映射,使得两个字符串相同。例如,JWPUDJSTVP重排后可以得到WJDUPSJPVT,然后把每个字母映射到它前一个字母(B->A,C->B,…,Z->Y,A->Z),得到VICTORIOUS。输入两个字符串,输入YES或者NO。
样例输入:
JWPUDJSTVP
VICTORIOUS
MAMA
ROME
HAHA
HEHE
AAA
AAA
NEERCISTHEBEST
SECRETMESSAGES
样例输出:
YES
NO
YES
YES
NO
分析:既然字符串可以重排,则每个字母的位置并不重要,重要的是每个字母出现的次数。这样可以统计两个字符串中各个字母出现的次数,并用两个数组来储存。那么只要这两个数组中存的内容一模一样就可以达到题目所要求的。但是存在一个障碍,就是这两个数组都是无序的,所以首先得先将这两个数组排个序,然后对比这两个数组,判断是否完全相同。
下面贴代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 105
int cmp(const void *a,const void *b) //①
{
return *(int *)a-*(int *)b;
}
int main()
{
char s[maxn],c[maxn];
while(memset(s,0,sizeof(s))&&memset(c,0,sizeof(c))&&(scanf(“%s%s”,s,c))!=EOF) //②
{
int a[26]={0};
int b[26]={0};
for(int i=0;i<26;i++)
{
for(int j=0;j<strlen(s);j++)
{
if((‘A’+i)==s[j]) a[i]++;
if((‘A’+i)==c[j]) b[i]++;
}
}
qsort(a,26,sizeof(int),cmp); //①
qsort(b,26,sizeof(int),cmp);
int k=1;
for(int i=0;i<26;i++)
{
if(a[i]!=b[i])
{
k=0;
break;
}
}
if(!k)
printf(“NO\n”);
else printf(“YES\n”);
}
return 0;
}
PS:①在C语言中stdlib.h头文件中有一个qsort库函数,实现了著名的快速排序法,它的函数声明是
void qsort(void *base,size_t num,size_t size,int (*comparator)(const void*,const void*));
前三个参数分别是待排序的的数组起始地址、元素个数和每个元素的大小。最后一个参数比较特别,是一个指向函数的指针,一般就是函数名。该函数应当具有这样的形式:
int cmp(const void*,const void*) {…}
在这里,cmp函数即为
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
一般地,需要先把参数a和b转化为真实的类型,这里就是*(int *)a,然后让cmp函数当a<b,a=b,a>b时分别返回负数、0、正数即可。
②在while的括号里可以用&&来写多个语句