我正在尝试使用 needleman 解决“最长公共子序列”问题。
示例:输入:text1 = "abcde", text2 = "ace" 输出:3
解释:最长的公共子序列是 "ace",它的长度是 3。
对于 text1 =“ezu”和 text2 =“ubm”的情况,我对算法应该如何工作感到非常困惑。
Needleman 矩阵是(假设不匹配的成本是 -3,差距的成本是 -4 和匹配是 1):
X | - | 你 | b | 米 |
---|---|---|---|---|
- | 0 | -4 | -8 | -12 |
e | -4 | -3 | -7 | -11 |
z | -8 | -7 | -6 | -10 |
你 | -12 | -7 | -10 | -9 |
现在算法状态从矩阵的底角回溯,并且:
- 如果 text[i] == text[j] => 向上移动对角线
- 否则移动到上下之间的最大值。
因此,从 -9 开始,我必须在 -10 和 -10 之间进行选择(我应该向上还是向下?),无论做出何种决定,我都不会遇到这种情况 [i,j] = [3,1]
我的代码:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.length();
int n = text2.length();
vector<vector<int>> vec(m+1, vector(n+1,0));
int mismatch = -3;
int gap = -4;
int match = 1;
for (int i = 1; i <= m; i++) {
vec[i][0] = vec[i-1][0] + gap;
}
for (int i = 1; i <= n; i++) {
vec[0][i] = vec[0][i-1] + gap;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
int cost = 0;
if (text1[i-1] != text2[j-1]) {
cost = max(vec[i-1][j-1]+ mismatch, min(vec[i-1][j]+gap, vec[i][j-1]+gap));
} else {
cost = match + vec[i-1][j-1];
}
vec[i][j] = cost;
}
}
int matchLen = 0;
int i = m;
int j = n;
while (i >0 && j >0) {
if (text1[i-1] == text2[j-1]) {
matchLen++;
i--;
j--;
} else if (i > 0 && j > 0) {
if (vec[i-1][j] > vec[i][j-1]) {
i--;
} else {
j--;
}
} else {
break;
}
}
return matchLen;
}
谢谢!