codewars第29题
最长的共同子序列(LCS)问题是找到一组序列中所有序列共有的最长子序列的问题。
它不同于寻找共同子串的问题:与子串不同,子序列不需要占据原始序列内的连续位置。
任务
编写一个lcs接受两个strings 的函数,并返回它们最长的公共子序列.
例如:
lcs( “abcdef”, “abc” ) => “abc”
lcs( “abcdef”, “acf” ) => “acf”
lcs( “132535365”, “123456789” ) => “12356”
lcs( “abcdefghijklmnopq”, “apcdefghijklmnobq” ) => “acdefghijklmnoq”
分析:
这道题我采用表格法求解,将s1作为表格的行,s2作为表格的列。通过两层循环嵌套访问比较s1和s2在不同下标下的值,如果相同则当前单元格的值为 i-1,j-1的单元格值+1.否则该单元格的值等于其左边或上边最大单元格的值。
if (x.empty() || y.empty())
{
return "";
}
int xlen = x.size();
int ylen = y.size();
std::vector<std::vector<int>> chess;
chess.resize(xlen +1);
chess[0].resize(ylen + 1, 0);
for (int i=1;i <=xlen;i++)
{
chess[i].resize(ylen+1,0);
for (int j=1;j <=ylen;j++)
{
if (x[i-1] ==y[j-1])
{
chess[i][j] = chess[i - 1][j - 1] + 1;
}
else
{
chess[i][j] = std::max(chess[i][j - 1], chess[i - 1][j]);
}
}
}
接下来从最后一个单元格的行下标和列下标开始遍历,如果对应的相等字符相等,则行号和列号同时减1,否则比较该单元格左边与上边的单元格值,如果上边大,则行-1,否则列-1
std::string strResults;
while (xlen != 0 && ylen != 0)
{
if (x[xlen-1] ==y[ylen-1])
{
strResults.push_back(x[xlen - 1]);
xlen--;
ylen--;
continue;
}
if (chess[xlen][ylen-1] >chess[xlen -1][ylen])
{
ylen--;
}
else
{
xlen--;
}
}
std::reverse(strResults.begin(), strResults.end());
return strResults;