📌  相关文章
📜  国际空间研究组织 | ISRO CS 2017 |问题 61(1)

📅  最后修改于: 2023-12-03 14:50:47.855000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2017 |问题 61

题目描述

有一个长度为 n,只包含小写字母的字符串 s,和一个正整数 k。保证 nk 的倍数。我们把 s 分成长度为 kn/k 个子串。对于每个子串,可以通过交换其中任意两个字符使其变得更小。求交换完所有子串后,最小的字典序是多少。

输入
  • 第一行包含整数 T,表示测试用例的数量。
  • 接下来 T 行,每行包含两个正整数 nk,以及一个长度为 n 的字符串 s,描述一个测试用例。
输出

对于每个测试用例,输出一行,一个字符串表示交换后最小的字典序是多少。

示例

输入:

2
6 3 abdcba
6 3 abcadc

输出:

`abcdab`
`aabccd`
解析

题目中给出了字符串和子串的长度,可以考虑将每一个子串进行排序,通过排序后的结果直接组合为最终结果即可。排序的效率可以考虑使用计数排序,时间复杂度为 $O(n+k)$。

代码实现
def min_lexicographical(s: str, k: int) -> str:
    n = len(s)
    t = n // k
    res = ""
    for i in range(t):
        sub = s[i * k:(i + 1) * k]
        cnt = [0] * 26
        for c in sub:
            cnt[ord(c) - ord('a')] += 1
        min_char = 'a'
        while cnt[ord(min_char) - ord('a')] == 0:
            min_char = chr(ord(min_char) + 1)
        for j in range(k):
            if sub[j] == min_char:
                res += min_char
                cnt[ord(min_char) - ord('a')] -= 1
            else:
                cnt[ord(sub[j]) - ord('a')] -= 1
        res += sub[0]
    return res

n = int(input())
for _ in range(n):
    s_len, k_len, s = input().split()
    k = int(k_len)
    res = min_lexicographical(s, k)
    print(res)

代码中先是将字符串拆分成若干个子串,对于每一个子串使用计数排序确定最终子串的最小字典序。最终将处理结果拼接成最终的字符串输出即可。