初学acmer--读《算法算法竞赛入门经典》笔记(12) P73-74

题目:古老的密码(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的括号里可以用&&来写多个语句

    原文作者:vaeloverforever
    原文地址: https://blog.csdn.net/vaeloverforever/article/details/77508833
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞