📜  门| GATE-CS-2016(套装1)|问题 26(1)

📅  最后修改于: 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码之和最大的值即可。

代码实现

Python代码

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)

Java代码

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);
    }
}