本文总结一下一些双字符串的DP问题。具体解法是要建立以两个字符串为边的矩阵。
vector<vector<int>> dp(lenA+1, vector<int>(lenB+1, 0)); \\ 要加1
dp[i][j] 为以A[i]结尾,和B[j]结尾的满足条件解。
0 a b c d
0
a
c
m
n
Longest Common Sub-sequence:
这道题的点是sub-sequence可以不连续。
dp[i][j] = 以A[i], B[j]为结尾,的最长sub-sequence长度。通项公式为
if(A[i] == B[j]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
int longestRepeatingSubsequence(string& str) {
// Write your code here
int len = str.length();
vector<vector<int>> dp(len+1, vector<int>(len+1, 0));
for(int i=1; i<=len; i++){
for(int j=1; j<=len; j++){
if(str[i-1] == str[j-1] && i != j){
dp[i][j] = 1 + dp[i-1][j-1];
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[len][len];
}
Longest Common Substring:
这道题要点是sub-string必须连续,
dp[i][j] = 以A[i], B[j]为结尾,的最长sub-string长度 (必须包含A[i], B[j])。通项公式为:
if(A[i] == B[j]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = 0;
然后新添一个max_len变量,打擂台, 找最长。
int longestCommonSubstring(string &A, string &B) {
// write your code here
if(A.empty() || B.empty()) return 0;
int lenA = A.size(), lenB = B.size();
vector<vector<int>> dp(lenA+1, vector<int>(lenB+1, 0));
int max_len = 0;
for(int i=1; i<=lenA; i++){
for(int j=1; j<=lenB; j++){
if(A[i-1] == B[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = 0;
}
if(dp[i][j] > max_len) max_len = dp[i][j];
}
}
return max_len;
}
Edit Distance
这道题的要点是下面的表达式。表示新加一个,删除一个,和edit一个。
dp[i][j]为以A[i], B[j]为结尾的最短edit distance。通项公式为:
dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1;
int minDistance(string word1, string word2) {
// write your code here
if(word1.empty()) return word2.length();
else if(word2.empty()) return word1.length();
int lenA = word1.length(), lenB = word2.length();
vector<vector<int>> dp(lenA+1, vector<int>(lenB+1, 0));
for(int i=0; i<=lenA; i++){
dp[i][0] = i;
}
for(int i=0; i<=lenB; i++){
dp[0][i] = i;
}
for(int i=1; i<=lenA; i++){
for(int j=1; j<=lenB; j++){
if(word1[i-1] == word2[j-1]){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1;
}
}
}
return dp[lenA][lenB];
}