712[Medium]: Minimum ASCII Delete Sum for Two Strings

Part1:题目描述

Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal.

Example 1:

Input: s1 = "sea", s2 = "eat"
Output: 231
Explanation: Deleting "s" from "sea" adds the ASCII value of "s" (115) to the sum.
Deleting "t" from "eat" adds 116 to the sum.
At the end, both strings are equal, and 115 + 116 = 231 is the minimum sum possible to achieve this.

Example 2:

Input: s1 = "delete", s2 = "leet"
Output: 403
Explanation: Deleting "dee" from "delete" to turn the string into "let",
adds 100[d]+101[e]+101[e] to the sum.  Deleting "e" from "leet" adds 101[e] to the sum.
At the end, both strings are equal to "let", and the answer is 100+101+101+101 = 403.
If instead we turned both strings into "lee" or "eet", we would get answers of 433 or 417, which are higher.

Note:

  • 0 < s1.length, s2.length <= 1000.
  • All elements of each string will have an ASCII value in [97, 122].

Part2:解题思路

  本来就是打算用一个题目检验一下对于最长公共子串和公共子序列问题的掌握情况,所以看到这道题第一反应就是想着向最长公共子序列的方向靠拢,所以得到的思路就是:找出最长公共子序列的ascii码和sumMax,用2个字符串的ASCII码和(sum1+sum2)减去2*sumMax。这样的代码就和上一篇博客里基本一样,唯一不同的是这次dp[i][j]里存的是最长公共子序列的ASCII和。(这一段代码见注释掉的函数部分)
  按照上面思路打出来的代码,在leetcode上也是过了的。但是我总觉得找出最长公共子序列删掉只能保证删除的序列是最长的但是ASCII码和是不是最大的我是没有办法肯定的。所以我就想,不如直接对我们要找的量——最小ASCII码和进行动态规划,下面是动态规划方程:

当某段字符串长度为0时,要删除的最小ASCII码和即为长度不为0的那一段字符串的序列的ASCII码和
当2段字符串都不为0时,如果2段字符串的末尾的字符相等,这个字符是不计入我们要的值(要删除掉的字符的ASCII值值和)的
2段字符串都不为0时,如果2段字符串的末尾的字符不相等,2种情况取较小的那个

Part3:代码

#include<iostream> 
#include<cstring>
#include<algorithm> 

using namespace std;
/*
int minimumDeleteSum(string s1, string s2) {
	int result = 0;
	int sum1 = 0;
	int sum2 = 0;
	int sumMax = 0;
	int length1 = s1.length();
	int length2 = s2.length();
	// 存放长度为i的s1的子串与长度为j的s2的子串的最长公共子序列的ASCII码和 
	int** dp = new int*[length1 + 1];
	for (int i = 0; i < length1+1; i++) {
		dp[i] = new int[length2 + 1];
	}
	for (int i = 0; i < length1 + 1; i++) {
		for (int j = 0; j < length2+1; j++) {
			dp[i][j] = 0;
		}
	}
	for (int i = 0; i < length1; i++) {
		sum1 += s1[i];
	}
	for (int i = 0; i < length2; i++) {
		sum2 += s2[i];
	}
	for (int i = 0; i <= length1; i++) {
		for (int j = 0; j <= length2; j++) {
			if (i == 0 || j == 0) {
				dp[i][j] = 0;
			} else if(s1[i-1] == s2[j-1]) {
				dp[i][j] = s1[i - 1] + dp[i - 1][j - 1];
			} else {
				dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
			}
			if (dp[i][j] > sumMax) {
			    sumMax = dp[i][j];
			}
		}
	}
// cout << "sumMax is " <<  sumMax << endl;
	result = sum1 - sumMax + sum2 - sumMax;
	return result;
}
*/

int minimumDeleteSum(string s1, string s2) {
	int length1 = s1.length();
	int length2 = s2.length();
	int sum1 = 0;
	int sum2 = 0;
	for (int i = 0; i < length1; i++) {
		sum1 += s1[i];
	}
	for (int i = 0; i < length2; i++) {
		sum2 += s2[i];
	}
	// 存放长度为i的s1的子串与长度为j的s2的子串的删除字符的最小ASCII码和
	int** dp = new int*[length1 + 1];
	for (int i = 0; i < length1+1; i++) {
		dp[i] = new int[length2 + 1];
	}
	for (int i = 0; i < length1 + 1; i++) {
		for (int j = 0; j < length2+1; j++) {
			dp[i][j] = 0;
		}
	}
	for (int i = 0; i <= length1; i++) {
		for (int j = 0; j <= length2; j++) {
			if (i == 0 && j == 0) {
				dp[i][j] = 0;
			} else if (i == 0 && j != 0) {
				for (int m = 0; m < j; m++) {
					dp[i][j] += s2[m];
				}
			} else if(j == 0 && i !=0) {
				for (int m = 0; m < i; m++) {
					dp[i][j] += s1[m];
				}
			} else if(s1[i-1] == s2[j-1]) {
				dp[i][j] = dp[i - 1][j - 1];
			} else {
				dp[i][j] = min((s1[i - 1] + dp[i - 1][j]), (s2[j - 1] + dp[i][j - 1]));
			}
		}
	}
	return dp[length1][length2];
}

int main() {
	string s1, s2;
	cin >> s1;
	cin >> s2;
	cout << minimumDeleteSum(s1, s2) << endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值