文章目录
- 115.不同的子序列
- [[583. 两个字符串的删除操作](https://leetcode.cn/problems/delete-operation-for-two-strings/description/)](#583. 两个字符串的删除操作)
- 72.编辑距离
115.不同的子序列
dp数组表示s和t中前i-1
和j-1
项中s中出现过的t的次数,递推公式中当选择到s的第i-1的元素和t[j-1]相等时,需要考虑两种情况,第一种是选择用s[i-1]这个元素和t[j-1]匹配,那么dp[i][j]就应该是dp[i-1][j-1],如果不使用s[i-1]的话,就应该是和dp[i-1][j]相同,因此dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
。当s[i-1]不等于t[j-1]时,就相当于是不使用s[i-1]和t[:j]匹配的情况,因此赋值为dp[i-1][j]。
python
class Solution:
def numDistinct(self, s: str, t: str) -> int:
len1 = len(s)
len2 = len(t)
dp = [[0]* (len2+1) for _ in range(len1+1)] # dp[i][j] 前一位是s后一位是t,t不变在s中删减,当t=''的时候dp[i][0]应该为1
for d in dp:
d[0] = 1
for i in range(1, len1+1):
for j in range(1, len2+1):
if s[i-1] == t[j-1]:
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
else:
dp[i][j] = dp[i-1][j]
return dp[-1][-1]
583. 两个字符串的删除操作
其实就是找两个数组相同的公共子序列长度,最后输出的时候拿两个数组的长度和减去两倍的最大公共子序列长度就可以。
python
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
len1 = len(word1)
len2 = len(word2)
dp = [[0]*(len2+1) for _ in range(len1+1)] # dp[i][j]表示word1选择前i位,word2选择前j位的时候两个字符串相同字符的个数
for i in range(1, len1+1):
for j in range(1, len2+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return len1 + len2 - 2*dp[-1][-1]
72.编辑距离
本质上还是在找两个字符串的最长相同子序列,这里的增加操作和删除操作其实可以看作是同一种操作,只是在两个字符串上反过来,因此需要增加一个字符也可以看作是另一个字符种删除掉这个字符,所以当word1和word2的字符i和j不相等的时候,dp[i][j]在dp[i-1][j]即删除word1元素,dp[i][j-1]即删除word2元素,和dp[i-1][j-1]即替换元素中选择最小的,然后+1。还有一个重要的是初始dp的时候需要对所有一个为空另一个不为空的时候的dp赋予初值,初值就是那个字符串的长度。
python
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
len1 = len(word1)
len2 = len(word2)
dp =[[0] * (len2+1) for _ in range(len1+1)]
for i in range(len1+1):
dp[i][0] = i
for j in range(len2+1):
dp[0][j] = j
for i in range(1, len1+1):
for j in range(1, len2+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
return dp[-1][-1]