题目描述:
https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/
题目大意:
分别在两个字符串s1、s2中删去一些字符,使得两个字符串剩余的子串相同。求删去的字符ASCII码数之和最小值。
解题方法:
这道题是LCS最长公共子串的变式,求删去字符ASCII码数之和最小,也就是求字符ASCII码之和最大的公共子串。
在LCS问题中,我们构建dp矩阵,行数为s1字符串长度+1,列数为s2字符串长度+1,dp[i][j]表示s1[:i] 与s2[:j]的最长公共子串长度,初始值全为零
状态转移方程:
1 如果s1[i]==s2[j] :dp[i][j]=dp[i-1][j-1]+1
2 如果s1[i]!=s2[j]:dp[i][j]=max(dp[i-1][j],dp[i][j-1])
MASCS:
dp[i][j]表示s1[:i] 与s2[:j]的字符ASCII码之和最大的公共子串ASCII码之和,初始值全为零
状态转移方程:
1 如果s1[i]==s2[j] :dp[i][j]=dp[i-1][j-1]+ord(s1[i])
2 如果s1[i]!=s2[j]:dp[i][j]=max(dp[i-1][j],dp[i][j-1])
python 代码:
class Solution(object):
def minimumDeleteSum(self, s1, s2):
"""
:type s1: str
:type s2: str
:rtype: int
"""
dp = [[0]*(len(s2)+1) for _ in range(len(s1)+1)]
for i in range(1,len(s1)+1):
for j in range(1,len(s2)+1):
if s1[i-1]==s2[j-1]:
dp[i][j]=dp[i-1][j-1]+ord(s1[i-1])
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
return sum(map(ord,s1+s2)) - dp[-1][-1]*2
sum函数:
sum(iterable) 返回可迭代对象中所有元素的和
map函数:
map(function, iterable, ...) 输入一个或者多个可迭代对象,返回一个新的列表,列表中第i个元素为function(iterable(i))的计算结果
ord函数:
ord(c)输入一个字符,输出这个字符的ASCII码值
疑问:
这里有一个问题:
ASCII码之和最大的公共子串是最长的公共子串吗?
答:不一定
可以通过
aa# #aa两个字符串进行举反例证明,这里假设ord(#)>2*ord(a)