
题目描述
给定两个字符串 initial 和 target,你的任务是通过一系列操作改变 initial 以使它与 target 相同。
在一次操作中,您只能在 initial 字符串开头或结尾添加或删除一个字符。
返回将 initial 变为 target 所需的最小 操作次数。
 
示例 1:
输入:initial = "abcde", target = "cdef"
输出:3
解释:
从 initial 的开头删除 'a' 和 'b' 并添加 'f' 到结尾。
 
示例 2:
输入:initial = "axxy", target = "yabx"
输出:6
解释:
    
        
            | 操作 | 
            结果字符串 | 
        
        
            将 'y' 添加到开头 | 
            "yaxxy" | 
        
        
            | 从结尾删除 | 
            "yaxx" | 
        
        
            | 从结尾删除 | 
            "yax" | 
        
        
            | 从结尾删除 | 
            "ya" | 
        
        
            将 'b' 添加到结尾 | 
            "yab" | 
        
        
            将 'x' 添加到结尾 | 
            "yabx" | 
        
    
 
示例 3:
输入:initial = "xyz", target = "xyz"
输出:0
解释:
不需要任何操作,因为字符串已经相等。
 
 
提示:
    1 <= initial.length, target.length <= 1000 
    initial 和 target 只包含小写英文字母。 
解法
方法一:动态规划
我们不妨假设字符串 initial 和 target 的长度分别为 \(m\) 和 \(n\)。
根据题目描述,我们只需要求出 initial 和 target 的最长公共子串的长度 \(mx\),那么我们可以从 initial 中删除 \(m - mx\) 个字符,然后再添加 \(n - mx\) 个字符,即可将 initial 转换为 target,因此答案为 \(m + n - 2 \times mx\)。
我们可以使用动态规划的方法求出 initial 和 target 的最长公共子串的长度 \(mx\)。我们定义一个二维数组 \(f\),其中 \(f[i][j]\) 表示以 initial[i - 1] 和 target[j - 1] 结尾的最长公共子串的长度。那么我们可以得到状态转移方程:
\[
f[i][j] = \begin{cases}
f[i - 1][j - 1] + 1, & \textit{if } \textit{initial}[i - 1] = \textit{target}[j - 1], \\
0, & \textit{otherwise}.
\end{cases}
\]
那么 \(mx = \max f[i][j]\),最终答案为 \(m + n - 2 \times mx\)。
时间复杂度 \(O(m \times n)\),空间复杂度 \(O(m \times n)\)。其中 \(m\) 和 \(n\) 分别为字符串 initial 和 target 的长度。
 | class Solution:
    def minOperations(self, initial: str, target: str) -> int:
        m, n = len(initial), len(target)
        f = [[0] * (n + 1) for _ in range(m + 1)]
        mx = 0
        for i, a in enumerate(initial, 1):
            for j, b in enumerate(target, 1):
                if a == b:
                    f[i][j] = f[i - 1][j - 1] + 1
                    mx = max(mx, f[i][j])
        return m + n - mx * 2
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16  | class Solution {
    public int minOperations(String initial, String target) {
        int m = initial.length(), n = target.length();
        int[][] f = new int[m + 1][n + 1];
        int mx = 0;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (initial.charAt(i - 1) == target.charAt(j - 1)) {
                    f[i][j] = f[i - 1][j - 1] + 1;
                    mx = Math.max(mx, f[i][j]);
                }
            }
        }
        return m + n - 2 * mx;
    }
}
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18  | class Solution {
public:
    int minOperations(string initial, string target) {
        int m = initial.size(), n = target.size();
        int f[m + 1][n + 1];
        memset(f, 0, sizeof(f));
        int mx = 0;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (initial[i - 1] == target[j - 1]) {
                    f[i][j] = f[i - 1][j - 1] + 1;
                    mx = max(mx, f[i][j]);
                }
            }
        }
        return m + n - 2 * mx;
    }
};
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17  | func minOperations(initial string, target string) int {
    m, n := len(initial), len(target)
    f := make([][]int, m+1)
    for i := range f {
        f[i] = make([]int, n+1)
    }
    mx := 0
    for i, a := range initial {
        for j, b := range target {
            if a == b {
                f[i+1][j+1] = f[i][j] + 1
                mx = max(mx, f[i+1][j+1])
            }
        }
    }
    return m + n - 2*mx
}
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15  | function minOperations(initial: string, target: string): number {
    const m = initial.length;
    const n = target.length;
    const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
    let mx: number = 0;
    for (let i = 1; i <= m; ++i) {
        for (let j = 1; j <= n; ++j) {
            if (initial[i - 1] === target[j - 1]) {
                f[i][j] = f[i - 1][j - 1] + 1;
                mx = Math.max(mx, f[i][j]);
            }
        }
    }
    return m + n - 2 * mx;
}
  |