📜  门| GATE CS 2021 |设置 1 |问题 24(1)

📅  最后修改于: 2023-12-03 15:42:12.821000             🧑  作者: Mango

门| GATE CS 2021 |设置 1 |问题 24

题目描述

给定两个字符串S1和S2,S1的长度为n,S2的长度为m。将S1插入到S2中以形成新的字符串。让我们定义一个字符串得分为:两个相邻字符的距离乘以它们的ASCII码差的绝对值。插入S1后,求得最佳得分。

请编写一个函数 int bestScore(string S1, string S2) 以实现上述逻辑。函数输入输出如下:

输入

  • S1:一个长度为n的字符串,表示要插入到S2中的字符串。($1 \leq n \leq 2000$)
  • S2:一个长度为m的字符串,表示要插入字符串的目标字符串。($1 \leq m \leq 10^5$)

输出

  • 函数应返回一个整数,表示插入S1之后获得的最佳得分。
示例

示例1:

输入:
S1 = "he"
S2 = "talker"
输出:
219
解释:
将"he"插入"S2"的第2个字符之后得到"Mtalker",其得分为
(1)*(77-109) + (1)*(101-97) + (2)*(97-108) + (1)*(108-101) 
= -988 + 4 - 22 + 7 = -999
将"he"插入"S2"的第3个字符之后得到"tHalker",其得分为
(1)*(84-116) + (1)*(104-72) + (2)*(97-108) + (1)*(108-101) 
= -988 + 32 + 22 + 7 = -927
将"he"插入"S2"的第4个字符之后得到"taHlker",其得分为
(1)*(84-116) + (2)*(104-97) + (3)*(108-72) + (1)*(101-108) 
= -988 + 14 - 108 + 7 = -1075
...
得分最大为219
提示
  • 考虑动态规划的思想来实现此问题。
解题思路

本题是一道动态规划(DP)的经典问题。我们可以将插入新字符串的操作按照顺序进行,从S2的每一个字母开始尝试插入,计算出插入每个位置后可能所得的最佳结果,并记录这个最佳结果。得到了所有位置的最佳结果后,可以在这些结果中选择最佳的,并返回它的值。

因为最优步骤一定是按照顺序插入新字符串,所以我们可以用一个二维数组 dp[i][j] 来记录插入S1中前i个字符到S2中前j个字符最大的得分。因为得分是由“两个相邻字符的距离乘以它们的ASCII码差的绝对值”计算而来的,所以可以用定义数组 score[i][j] 来保存两个字符之间距离的权重。对于某个位置 dp[i][j],如果将S1中第i个字符插入到S2中第j个位置上,总得分为:上一个得分加上插入得分减去两个子串之间得分。

$$dp[i][j] = \max_{1 \leq k \leq j} dp[i-1][k] + \text{插入得分} - score[k][j-1]$$

因此,我们可以遍历所有的 ij,每次计算出上式的最大值即可。插入得分可以表示为 $\text{插入权重}\times\left|s_2\left(j\right)-s_1\left(i\right)\right|$。

$$\text{插入得分} = \text{插入权重} \times \left| \text{ASCII}(s_2(j)) - \text{ASCII}(s_1(i)) \right|$$

通过计算各个位置的得分,我们可以得出最佳的得分。

代码实现
#include <bits/stdc++.h>
using namespace std;

int bestScore(string S1, string S2) {
    int n = S1.length(), m = S2.length();
    vector<vector<int>> dp(n+1, vector<int>(m+1));
    vector<vector<int>> score(128, vector<int>(128));
    for(int i=0; i<128; i++){
        for(int j=0; j<128; j++){
            score[i][j] = abs(i-j);
        }
    }
    int res = 0;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            dp[i][j] = -0x3f3f3f3f;
            for(int k=j-1; k>=0; k--){
                dp[i][j] = max(dp[i][j], dp[i-1][k] + score[S1[i-1]][S2[j-1]] - score[S2[k]][S2[j-1]]);
                res = max(res, dp[i][j]);
            }
        }
    }
    return res;
}