Giả sử chúng ta có hai chuỗi S và T. Chúng ta phải tìm chuỗi các phép toán ngắn nhất thay đổi S thành T. Ở đây, các phép toán về cơ bản là xóa hoặc chèn một ký tự.
Vì vậy, nếu đầu vào giống như S ="xxxy" T ="xxyy", thì đầu ra sẽ là ["x", "x", "-x", "y", "+ y"], điều này có nghĩa là hai chữ x đầu tiên, sau đó xóa x thứ 3, sau đó đặt y rồi thêm y mới.
Để giải quyết vấn đề này, chúng tôi sẽ làm theo các bước sau -
- tạo một bảng dp có kích thước 505 x 505
- Xác định một hàm help (), điều này sẽ lấy i, j, S, T,
- nếu tôi giống với kích thước của S và j giống với kích thước của T, thì -
- return dp [i, j] =0
- nếu tôi giống với kích thước của S, thì -
- return dp [i, j] =1 + help (i, j + 1, S, T)
- nếu j giống với kích thước của T, thì -
- return dp [i, j] =1 + help (i + 1, j, S, T)
- nếu dp [i, j] không bằng -1, thì -
- trả về dp [i, j]
- dontDo:=1e5, del:=0, insert:=0
- nếu S [i] giống T [j] thì -
- dontDo:=help (i + 1, j + 1, S, T)
- del:=1 + help (i + 1, j, S, T)
- insert:=1 + help (i, j + 1, S, T)
- minVal:=min ({dontDo, del, insert})
- return dp [i, j] =minVal
- Xác định hàm getPath (), hàm này sẽ lấy i, j, S, T, curr, một mảng ret,
- nếu curr giống 0 và i giống với kích thước của S và j giống với kích thước của T, thì -
- trở lại
- nếu i
- chèn chuỗi (1, S [i]) vào cuối ret
- getPath (i + 1, j + 1, S, T, curr, ret)
- insert ("-" nối chuỗi (1, S [i])) vào cuối ret
- getPath (i + 1, j, S, T, curr - 1, ret)
- insert ("+" chuỗi nối (1, T [j])) vào cuối ret
- getPath (i, j + 1, S, T, curr - 1, ret)
Ví dụ (C ++)
Hãy cùng chúng tôi xem cách triển khai sau để hiểu rõ hơn -
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v) {
cout << "[";
for (int i = 0; i < v.size(); i++) {
cout << v[i] << ", ";
}
cout << "]" << endl;
}
int dp[505][505];
class Solution {
public:
int help(int i, int j, string& S, string& T) {
if (i == S.size() && j == T.size())
return dp[i][j] = 0;
if (i == S.size())
return dp[i][j] = 1 + help(i, j + 1, S, T);
if (j == T.size())
return dp[i][j] = 1 + help(i + 1, j, S, T);
if (dp[i][j] != -1)
return dp[i][j];
int dontDo = 1e5;
int del = 0;
int insert = 0;
if (S[i] == T[j])
dontDo = help(i + 1, j + 1, S, T);
del = 1 + help(i + 1, j, S, T);
insert = 1 + help(i, j + 1, S, T);
int minVal = min({dontDo, del, insert});
return dp[i][j] = minVal;
}
void getPath(int i, int j, string& S, string& T, int curr, vector<string>& ret) {
if (curr == 0 && i == S.size() && j == T.size())
return;
if (i < S.size() && j < T.size() && S[i] == T[j] && dp[i + 1][j + 1] == curr) {
ret.push_back(string(1, S[i]));
getPath(i + 1, j + 1, S, T, curr, ret);
}else if (dp[i + 1][j] + 1 == curr) {
ret.push_back("-" + string(1, S[i]));
getPath(i + 1, j, S, T, curr - 1, ret);
}else {
ret.push_back("+" + string(1, T[j]));
getPath(i, j + 1, S, T, curr - 1, ret);
}
}
vector<string> solve(string S, string T) {
memset(dp, -1, sizeof dp);
vector<string> ret;
int x = help(0, 0, S, T);
getPath(0, 0, S, T, x, ret);
return ret;
}
};
vector<string> solve(string source, string target) {
return (new Solution())->solve(source, target);
}
main(){
string S = "xxxy", T = "xxyy";
print_vector(solve(S, T));
} Đầu vào
"xxxy", "xxyy"
Đầu ra
[x, x, -x, y, +y, ]