问题描述
求两字符序列的最长公共字符子序列。
补充说明:
- 不强制要求子串的字符连续出现在原始的2个字符序列中。
- 测试字符序列,比如,
Name | Value |
---|
第1个字符序列 S[x] | {‘A’, ‘B’, ‘C’, ‘B’, ‘D’, ‘A’, ‘B’} |
第2个字符序列 W[y] | {‘B’, ‘D’, ‘C’, ‘A’, ‘B’, ‘A’} |
解决思路
确立状态方程
参考图1.表格所示,记 LCS(x, y) 为表格中的元素,该元素表示截止到第1序列中的字符‘x’和第2序列中的字符‘y’时已有多少个相同的字符个数,即公共子序列的长度。
图1.
⎧⎩⎨LCS(x,y)=LCS(x−1,y−1)+1,LCS(x,y)=max(LCS(x−1,y),LCS(x,y−1)),LCS(0,0)=0,if S(x) = W(y)if S(x) != W(y)if x = 0 or y = 0
图1.中箭头的方向表示当前的“公共子序列长度”继承自哪个前一个位置,这里,如果有
[LCS(x−1,y)=LCS(x,y−1),且 S(x) != W(y)]
的情况,则如
图1.所示,当前LCS(x, y)元素值优先继承自纵轴上方的那个(箭头↑)。由此,亦可以看出,最长公共子序列并非唯一的。
代码
#include
#include using namespace std;
#define ArraySize 16
int dp[ArraySize][ArraySize]={0};
void DpLCS(vector<char>::iterator pVecX, vector<char>::iterator pVecY, int x, int y);
int main(void)
{char cBufX[] &#61; {&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;B&#39;, &#39;D&#39;, &#39;A&#39;, &#39;B&#39;};char cBufY[] &#61; {&#39;B&#39;, &#39;D&#39;, &#39;C&#39;, &#39;A&#39;, &#39;B&#39;, &#39;A&#39;};vector<char> vecX, vecY;for (int i&#61;0; i<(sizeof(cBufX)/sizeof(char)); i&#43;&#43;){vecX.push_back(cBufX[i]); (vecX.at(i) &#61;&#61; vecY.at(j)){dp[i&#43;1][j&#43;1] &#61; dp[i][j]&#43;1;}else{dp[i&#43;1][j&#43;1] &#61; std::max(dp[i][j&#43;1], dp[i&#43;1][j]);}}}