[语言月赛202212] 盒武器

文章描述了一个编程挑战,要求重新排列字母顺序,使得给定的两个字符串`s`和`t`在新顺序下满足`t`字典序小于`s`。题目提供了两种解题思路,一种是逐个字符比较并调整,另一种是反转整个字母表。解决方案必须确保存在一种方式能令`t`的字典序小于`s`。
摘要由CSDN通过智能技术生成

题目描述

Aya 在网校共有两名助教,她们的网名分别为某 E 和 L 队。

Aya 热衷于开盒。他对两名助教使用了盒武器,得知某 E 的真实姓名为一个字符串 ss,L 队的真实姓名为一个字符串 tt。两个人的名字均只包含英文小写字母。

Aya 确信实力和姓名的字典序有关,姓名字典序越靠前,实力越强。

但是事实上,L 队的实力严格强于某 E。所以,你需要重新确定 2626 个英文小写字母的大小顺序,以保证 Aya 得到的结果与事实相符。

也就是说,请你重新定义 2626 个字母之间的大小关系,使得按照你新定义的大小关系比较 s,ts,t 两字符串的字典序时,满足 t < st<s。

字符串 tt 的字典序小于 ss 的字典序当且仅当满足如下两个条件之一:

  1. tt 是 ss 的一个前缀;
  2. 存在一个位置 j \leq \min(|s|, |t|)j≤min(∣s∣,∣t∣),使得对 1 \leq i < j1≤i<j 都有 s_i = t_isi​=ti​ 且 t_j < s_jtj​<sj​。其中两字符相比较的小于号是你重新定义的小于关系。

输入格式

输入的第一行为一个字符串 ss。
输入的第二行为一个字符串 tt。

输出格式

输出一行一个字符串,长度为 2626,\texttt{a} \sim \texttt {z}a∼z 这些字符在你的输出中均应恰好出现一次,以表示字母之间新定义的大小关系。

在输出中靠前位置的字母小于在输出中靠后位置的字母。

答案可能有多种,你只需要给出任意一组。

输入输出样例

输入 #1复制

b
a

输出 #1复制

abcdefghijklmnopqrstuvwxyz

说明/提示

数据规模与约定

  • 对于 30\%30% 的数据,|s|=|t|=1∣s∣=∣t∣=1;
  • 对于 60\%60% 的数据,|s|=|t|∣s∣=∣t∣;
  • 对于 100\%100% 的数据,1 \le |s|,|t| \le 10^61≤∣s∣,∣t∣≤106,且 s \neq ts=t。

数据保证存在一种方式,使得字典序上 t<st<s。

题目大意

给定两个字符串 ss 和 tt。重新定义 2626 个字母之间的大小关系,使得按照新定义的大小关系,tt 的字典序小于 ss 的字典序。

解析

提供两种做法。第一种比较容易想到,但是码量较大。第二种码量极短,但是可能有点难想到。

第一种做法如下:

我们注意到 t < st<s 的两个条件为「tt 是 ss 的一个前缀」或「存在一个位置 j \leq \min(|s|, |t|)j≤min(∣s∣,∣t∣),使得对 1 \leq i < j1≤i<j 都有 s_i = t_isi​=ti​ 且 t_j < s_jtj​<sj​」。自然而然地,t > st>s 的两个条件为「ss 是 tt 的一个前缀」或「存在一个位置 j \leq \min(|s|, |t|)j≤min(∣s∣,∣t∣),使得对 1 \leq i < j1≤i<j 都有 s_i = t_isi​=ti​ 且 t_j > s_jtj​>sj​」。

由于题目保证了 s \neq ts=t,因此 tt 与 ss 的关系只有以上四种可能。

考虑 t > st>s 的两个条件。对第一个条件,显然,我们不可能通过调整字母之间的大小关系使得 t < st<s,且题目保证了数据一定有解,所以这种情况一定不存在。

现在我们需要下手的情况只有一个了,即「存在一个位置 j \leq \min(|s|, |t|)j≤min(∣s∣,∣t∣),使得对 1 \leq i < j1≤i<j 都有 s_i = t_isi​=ti​ 且 t_j > s_jtj​>sj​」。

不难发现,这种情况下,我们只需要修改 t _ jtj​ 与 s _ jsj​ 的大小关系,使之满足 t _ j < s _ jtj​<sj​ 即可。因此,我们对这两位单独处理,其余的按照任意顺序输出即可。

以下为此做法的核心代码:

scanf("%s%s", s, t);
lenS = strlen(s);
lenT = strlen(t);
int ptr = 0, minLength = min(lenS, lenT);
while (ptr < minLength) {
	if (s[ptr] != t[ptr])
		break;
	++ptr;
}
if (ptr == minLength) {
	for (int i = 'a'; i <= 'z'; ++i) {
		printf("%c", i);
	}
} else {
	char a = t[ptr], b = s[ptr];
	printf("%c%c", a, b);
	for (int i = 'a'; i <= 'z'; ++i) {
		if (i != a && i != b)
			printf("%c", i);
	}
}

第二种做法如下:

由第一种做法,我们知道,如果 t > st>s,我们只需要修改「存在一个位置 j \leq \min(|s|, |t|)j≤min(∣s∣,∣t∣),使得对 1 \leq i < j1≤i<j 都有 s_i = t_isi​=ti​ 且 t_j > s_jtj​>sj​」条件下 s _ jsj​ 与 t _ jtj​ 的关系即可。

我们考虑,如果我们将整个字母表的大小关系反转,即 \texttt{z} < \texttt{y} < \cdots < \texttt{b} < \texttt{a}z<y<⋯<b<a,那么无论 s _ jsj​ 与 t _ jtj​ 是哪个字母,只要原来 s _ j < t _ jsj​<tj​,那么在反转后的字母表中,t _ jtj​ 一定小于 s _ jsj​。由此,我们即可保证 t < st<s。

所以这一种做法的代码量少得可怕,核心代码如下:

string s, t;
cin >> s >> t;
if (s > t) cout << "abcdefghijklmnopqrstuvwxyz" << endl;
else cout << "zyxwvutsrqponmlkjihgfedcba" << endl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值