题目## 题目
解题思路
这道题要求在字符串 s s s 上覆盖字符串 t t t 中的字符,得到字典序最大的结果。关键点是:
- 可以从 t t t 中选择任意字符覆盖 s s s 中的字符
- t t t 中的每个字符只能使用一次
- 不一定要用完 t t t 中的所有字符
- 需要得到字典序最大的结果
解题步骤:
- 将 t t t 中的字符排序(从大到小)
- 从左到右遍历
s
s
s,对于每个位置:
- 检查 t t t 中所有剩余字符,找到能使结果字典序最大的替换方案
- 如果找到更好的替换方案,则进行替换
- 输出最终结果
例如对于输入:
- s = “fedcba”
- t = “ee”
正确的处理过程:
- 对 t t t 排序得到 “ee”
- 遍历 s s s,在每个位置都尝试所有可能的替换
- 最终得到 “feeeba”(在 ‘d’ 和 ‘c’ 的位置用 ‘e’ 替换)
代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string s, t;
cin >> s >> t;
// 将t中的字符排序(从大到小)
sort(t.begin(), t.end(), greater<char>());
// 标记t中字符的使用情况
vector<bool> used(t.length(), false);
// 遍历s中的每个位置
for(int i = 0; i < s.length(); i++) {
char maxChar = s[i];
int maxIndex = -1;
string temp = s;
// 尝试用t中每个未使用的字符替换当前位置
for(int j = 0; j < t.length(); j++) {
if(!used[j]) {
temp[i] = t[j];
if(temp > s) { // 如果得到更大的字符串
s = temp;
maxIndex = j;
}
temp = s; // 恢复临时字符串
}
}
// 如果找到了更好的替换方案
if(maxIndex != -1) {
used[maxIndex] = true;
}
}
cout << s << endl;
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
String t = sc.next();
// 将t转换为字符数组并排序
char[] tArr = t.toCharArray();
Arrays.sort(tArr);
// 标记t中字符的使用情况
boolean[] used = new boolean[tArr.length];
char[] sArr = s.toCharArray();
// 遍历s中的每个位置
for(int i = 0; i < sArr.length; i++) {
String maxStr = new String(sArr);
int maxIndex = -1;
// 尝试用t中每个未使用的字符替换当前位置
for(int j = 0; j < tArr.length; j++) {
if(!used[j]) {
char[] temp = sArr.clone();
temp[i] = tArr[j];
String newStr = new String(temp);
if(newStr.compareTo(maxStr) > 0) {
maxStr = newStr;
maxIndex = j;
}
}
}
// 如果找到了更好的替换方案
if(maxIndex != -1) {
sArr = maxStr.toCharArray();
used[maxIndex] = true;
}
}
System.out.println(new String(sArr));
}
}
s = input()
t = input()
# 将s转换为列表以便修改
s = list(s)
# 将t排序(从大到小)
t = sorted(t, reverse=True)
used = [False] * len(t)
# 遍历s中的每个位置
for i in range(len(s)):
max_str = ''.join(s)
max_index = -1
# 尝试用t中每个未使用的字符替换当前位置
for j in range(len(t)):
if not used[j]:
temp = s.copy()
temp[i] = t[j]
new_str = ''.join(temp)
if new_str > max_str:
max_str = new_str
max_index = j
# 如果找到了更好的替换方案
if max_index != -1:
s = list(max_str)
used[max_index] = True
print(''.join(s))
算法及复杂度
- 算法:贪心算法。在每个位置都尝试所有可能的替换,选择能得到最大字典序的方案。
- 时间复杂度: O ( n m ) \mathcal{O}(nm) O(nm),其中 n n n 是字符串 s s s 的长度, m m m 是字符串 t t t 的长度。
- 空间复杂度: O ( n ) \mathcal{O}(n) O(n),需要存储字符串和临时数组。
解题思路
这是一道使用Huffman编码思想的问题,主要思路如下:
-
问题分析:
- 给定一个字符串,需要进行二进制编码
- 相同的字符必须使用相同的编码
- 要求编码后的总长度最短
-
解决方案:
- 统计每个字符的出现次数
- 使用优先队列(小顶堆)合并最小的两个长度
- 类似Huffman树的构建过程
-
关键点:
- 先对字符串排序,便于统计连续相同字符
- 使用优先队列维护最小的两个长度
- 每次合并后将新长度加入队列
代码
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
int getMinEncodingLength(string s) {
// 先排序,便于统计
sort(s.begin(), s.end());
// 使用小顶堆存储每组相同字符的长度
priority_queue<int, vector<int>, greater<int>> pq;
// 统计连续相同字符的长度
for (int i = 0; i < s.length();) {
int j = i;
while (j < s.length() && s[j] == s[i]) {
j++;
}
pq.push(j - i); // 将该字符出现的次数加入队列
i = j;
}
// 类似Huffman树的构建过程
int totalLength = 0;
while (pq.size() > 1) {
int a = pq.top(); pq.pop();
int b = pq.top(); pq.pop();
totalLength += a + b; // 合并两个最小的长度
pq.push(a + b); // 将合并后的长度放回队列
}
return totalLength;
}
int main() {
string s;
while (cin >> s) {
cout << getMinEncodingLength(s) << endl;
}
return 0;
}
import java.util.*;
public class Main {
public static int getMinEncodingLength(String s) {
// 转换为字符数组并排序
char[] chars = s.toCharArray();
Arrays.sort(chars);
// 使用优先队列(小顶堆)存储每组相同字符的长度
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 统计连续相同字符的长度
for (int i = 0; i < chars.length;) {
int j = i;
while (j < chars.length && chars[j] == chars[i]) {
j++;
}
pq.offer(j - i); // 将该字符出现的次数加入队列
i = j;
}
// 类似Huffman树的构建过程
int totalLength = 0;
while (pq.size() > 1) {
int a = pq.poll();
int b = pq.poll();
totalLength += a + b; // 合并两个最小的长度
pq.offer(a + b); // 将合并后的长度放回队列
}
return totalLength;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s = sc.next();
System.out.println(getMinEncodingLength(s));
}
}
}
from heapq import heappush, heappop
def get_min_encoding_length(s: str) -> int:
# 先排序,便于统计
s = sorted(s)
# 使用小顶堆存储每组相同字符的长度
heap = []
# 统计连续相同字符的长度
i = 0
while i < len(s):
j = i
while j < len(s) and s[j] == s[i]:
j += 1
heappush(heap, j - i) # 将该字符出现的次数加入堆
i = j
# 类似Huffman树的构建过程
total_length = 0
while len(heap) > 1:
a = heappop(heap)
b = heappop(heap)
total_length += a + b # 合并两个最小的长度
heappush(heap, a + b) # 将合并后的长度放回堆
return total_length
# 处理输入
while True:
try:
s = input()
print(get_min_encoding_length(s))
except EOFError:
break
算法及复杂度
- 算法:贪心(Huffman编码思想)
- 时间复杂度: O ( n log n ) \mathcal{O}(n\log n) O(nlogn) - 排序需要 O ( n log n ) \mathcal{O}(n\log n) O(nlogn),堆操作需要 O ( k log k ) \mathcal{O}(k\log k) O(klogk), k k k 为不同字符数
- 空间复杂度: O ( k ) \mathcal{O}(k) O(k) - k k k 为不同字符数,需要优先队列存储
738

被折叠的 条评论
为什么被折叠?



