📅  最后修改于: 2023-12-03 15:42:18.535000             🧑  作者: Mango
给定两个文本字符串A和B,由小写英文字母组成。定义A的一个子串为A的一个连续的一段字符,它们可能不同于A本身,B的一个字串为B的一个连续的一段字符,它们可能不同于B本身。现在A和B各有一个正整数k,你可以将A中的一个长度为k的连续子串与B中的一个长度为k的连续子串交换,要求ASCII码值之和最大。给出满足要求的最大的ASCII码值之和,如果无法通过交换实现,则输出0。
例如,给定A仅包含"abcde"和B仅包含"bcdea",k=3,那么我们可以交换A中的"a"和B中的"d"(从A中剪掉"abc"和从B中剪掉"dea")。交换后,A变为"decde",B也变为"bacae"。在这种情况下,最大的ASCII码值之和是a+d的ASCII码值再加上从交换后的A和B中得到的字符串的ASCII码值,即97+100+99+98+98+97=589。
输入格式: 第一行由两个正整数n和k组成(n≤106,1≤k≤5)。下一行是字符串A;下一行是字符串B。
输出格式: 仅一行,即所需的答案。
5 3
abcde
bcdea
589
题目要求我们交换A和B中各自k个连续的字符,使得两个字符串的ASCII码之和最大。那么我们可以考虑遍历所有k个长度的子字符串,分别计算他们的ASCII码值之和。我们可以使用哈希表来记录这些子字符串的ASCII码值之和,并且将其按照ASCII码值之和从大到小排序。将A和B的子字符串分别存储在两个数组中,我们便可以使用一个双指针来遍历这两个数组,同时统计A和B交换后的字符串的ASCII码之和。最后返回ASCII码之和最大的值即可。
def get_ascii_sum(s):
"""计算某个字符串的ASCII码值之和"""
return sum(map(ord, list(s)))
n, k = map(int, input().split())
a = input().strip()
b = input().strip()
subs_a, subs_b = [], []
# 遍历所有k长度子字符串,计算其ASCII码值之和
for i in range(n-k+1):
subs_a.append((a[i:i+k], get_ascii_sum(a[i:i+k])))
subs_b.append((b[i:i+k], get_ascii_sum(b[i:i+k])))
# 将两个数组按照ASCII码值之和从大到小排序
subs_a.sort(key=lambda x: x[1], reverse=True)
subs_b.sort(key=lambda x: x[1], reverse=True)
# 初始化最大的ASCII码之和
max_ascii_sum = get_ascii_sum(a) + get_ascii_sum(b)
# 双指针扫描subs_a和subs_b,分别计算交换后的字符串的ASCII码和
i, j = 0, 0
while i<len(subs_a) and j<len(subs_b):
a_sub, a_sum = subs_a[i]
b_sub, b_sum = subs_b[j]
# 如果两个子字符串不相等,则进行交换并计算新的ASCII码值之和
if a_sub!=b_sub:
new_a = a[:a.index(a_sub)] + b[b.index(b_sub):b.index(b_sub)+k] + a[a.index(a_sub)+k:]
new_b = b[:b.index(b_sub)] + a[a.index(a_sub):a.index(a_sub)+k] + b[b.index(b_sub)+k:]
new_sum = get_ascii_sum(new_a) + get_ascii_sum(new_b)
# 更新最大ASCII码之和
if new_sum > max_ascii_sum:
max_ascii_sum = new_sum
# 双指针遍历子字符串数组
if a_sum > b_sum:
i += 1
else:
j += 1
print(max_ascii_sum if max_ascii_sum>get_ascii_sum(a)+get_ascii_sum(b) else 0)
import java.util.*;
public class Main {
public static int getAsciiSum(String s) {
int sum = 0;
for(int i=0; i<s.length(); i++) {
sum += (int) s.charAt(i);
}
return sum;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] nums = sc.nextLine().split(" ");
int n = Integer.parseInt(nums[0]), k = Integer.parseInt(nums[1]);
String a = sc.nextLine();
String b = sc.nextLine();
List<String[]> subsA = new ArrayList<>(); //保存字符串a的所有长度为k的子字符串及其 ASCII 码值之和
List<String[]> subsB = new ArrayList<>(); //保存字符串b的所有长度为k的子字符串及其 ASCII 码值之和
for(int i=0; i<=n-k; i++) {
subsA.add(new String[]{a.substring(i, i+k), String.valueOf(getAsciiSum(a.substring(i, i+k)))});
subsB.add(new String[]{b.substring(i, i+k), String.valueOf(getAsciiSum(b.substring(i, i+k)))});
}
//根据子字符串的 ASCII 码值之和从大到小进行排序
subsA.sort((o1, o2) -> Integer.parseInt(o2[1])-Integer.parseInt(o1[1]));
subsB.sort((o1, o2) -> Integer.parseInt(o2[1])-Integer.parseInt(o1[1]));
String[] aSub = new String[2]; //保存字符串a中与字符串b中某个子串交换后的新子串
String[] bSub = new String[2]; //保存字符串b中与字符串a中某个子串交换后的新子串
String newA, newB;
int maxAsciiSum = getAsciiSum(a) + getAsciiSum(b); //初始化最大的 ASCII 码值之和
int i = 0, j = 0; //双指针遍历 subsA 和 subsB
while(i<subsA.size() && j<subsB.size()) {
String aStr = subsA.get(i)[0], bStr = subsB.get(j)[0];
int aSum = Integer.parseInt(subsA.get(i)[1]), bSum = Integer.parseInt(subsB.get(j)[1]);
//如果当前两个子字符串不相等,则进行交换并计算新的 ASCII 码值之和,更新 maxAsciiSum
if(!aStr.equals(bStr)) {
newA = a.replace(aStr, bStr.substring(0, k));
newB = b.replace(bStr, aStr.substring(0, k));
int newAsciiSum = getAsciiSum(newA) + getAsciiSum(newB);
if(newAsciiSum > maxAsciiSum) {
maxAsciiSum = newAsciiSum;
}
}
//双指针遍历两个数组
if(aSum > bSum) {
i++;
} else {
j++;
}
}
System.out.print(maxAsciiSum > getAsciiSum(a) + getAsciiSum(b) ? maxAsciiSum : 0);
}
}