📅  最后修改于: 2023-12-03 15:09:40.338000             🧑  作者: Mango
给定两个字符串 S 和 T,需要判断最少需要删除或者插入多少个字符才可以使它们相等。本文将提供两种常见的方法。
若将两个字符串变得相等,显然需要知道这两个字符串各前缀的最长公共子序列的长度,具体来说,
结合这两种情况,我们可以列出动态规划方程:
$$dp[i][j]=\begin{cases} 0&i=0,j=0\ dp[i-1][j-1]+1& s_{i}=t_{j}\ \min{dp[i-1][j],dp[i][j-1]}+1& s_{i}\neq t_{j} \end{cases}$$
其中 $dp[i][j]$ 表示字符串 $S$ 前 $i$ 个字符和字符串 $T$ 前 $j$ 个字符的最少操作次数。
def minDistance(s: str, t: str) -> int:
m, n = len(s), len(t)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(m + 1):
dp[i][0] = i
for j in range(n + 1):
dp[0][j] = j
for i in range(1, m + 1):
for j in range(1, n + 1):
if s[i - 1] == t[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1
return dp[m][n]
复杂度分析:
设 $m=\lvert S\rvert$,$n=\lvert T\rvert$。
当然,也可以用另一种方式来求出这个最长公共子序列的长度。具体来说,我们可以定义 $dp[i][j]$ 为字符串 $S$ 的前 $i$ 个字符与字符串 $T$ 的前 $j$ 个字符的最长公共子序列的长度,那么最少需要删除或者插入的字符数就是 $m + n - 2\times dp[m][n]$。
为什么呢?因为最长公共子序列把两个字符串各减去了一些字符,所以两个字符串相等所需的删除或者插入次数就是两个字符串长度减去最长公共子序列的长度的两倍。
def minDistance(s: str, t: str) -> int:
m, n = len(s), len(t)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if s[i - 1] == t[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 m + n - 2 * dp[m][n]
复杂度分析:
设 $m=\lvert S\rvert$,$n=\lvert T\rvert$。