古老的密码(Ancient Cipher,UVa1339)(算法竞赛入门经典 例题4-1)C++

题目:给定两个不超过100的字符串,判断是否可以做到将其中一个字符串通过重排和映射的操作,使得两个字符串相同。例如,JWPUDJSTVP重排后可以得到WJDUPSJPVT,然后每个字母只要通过一次映射,映射到前一个字母,可以得到VICTORIOUS(映射可以多次多样)。输入两个字符串,输出YES或者NO。

思路:这里要用比较抽象的思想,由于字符串可以进行任意的重排映射,因此只要两个字符串各个字母的数量在经过排序后发现相等,那么可以通过任意的操作使得两个字符串变成一样。可以理解为字母可以任意变化,但相同的字母只能变化成一样的字母,如AABBC可以得到GZZXX,他们的各字母数量经过排序都是122。

因此我们只要统计出两个字符串各字母的数量,然后对他们排序后比较是否相同即可,相同即YES,不相同即NO。

内容有参考《算法竞赛入门经典》的分析,代码已通过vj测试!

#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
char s1[105], s2[105];                              //输入两串字符串
int let1[26], let2[26];                             //记录s1,s2中各字母出现的个数

int cmp_int(const void* let1, const void* let2)
{
	return *(int*)let1 - *(int*)let2;
}

int main()
{
	while (cin >> s1)
	{
		memset(let1, 0, sizeof(let1));              //每次循环对字母计数的数组清零
		memset(let2, 0, sizeof(let1));
		cin >> s2;
		for (int j = 0; j < strlen(s1); j++)        //计算s1中各字母出现次数
		{
			let1[s1[j]-65]++;
		}
		for (int k = 0; k < strlen(s2); k++)        //计算s2中各字母出现次数
		{
			let2[s2[k]-65]++;
		}
		//现在得到了各字母在两个字符串中的数量的数组,比如一个是3241,一个是1243
		//那么如果经过排序发现两个数组相等,说明字母的数量可以做到一一对应,如都是1234(都是一共出现四种字母,数量分别为1、2、3、4),映射重排之后自然可以得到相同的字符串。
		//因此接下来只要对let数组排序即可。
		qsort(let1, 26, sizeof(let1[0]), cmp_int);
		qsort(let2, 26, sizeof(let2[0]), cmp_int);
		int flag = 1;
		for(int i=0;i<26;i++)
			if (let1[i] != let2[i])
			{
				flag = 0;
				break;
			}
		if (flag == 0)
			cout << "NO" << endl;
		else
			cout << "YES" << endl;
	}

	return 0;
}

接下来简单介绍一下所用的排序函数:

头文件#include<stdlib.h>,所用函数qsort快速排序,其声明如下:

void qsort(void*base ,size_t num ,size_t size ,int(*comparator)(const void*,const void*));

其中的四个参数分别是待排序数组的首地址,数组元素个数,每个元素字节大小,以及最后一个参数是一个函数。

前三个很好理解,按照需求填入即可,然而最后一个参数需要我们根据我们需求自定义,然后传入这个函数作为快排函数的参数。(可以参考代码第八行的函数)

这个函数是一个自定义函数,有自己的模板,要求我们编写来告诉qsort函数要根据什么进行排序。具体知识请参考相关的博客,不作多解释。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值