问题是给定字符串x和y,求出两个当中最长的公共子序列。比如x=abcdef y=acefg,那么他们的最长公共子序列就是acef。就是求x的所有可能的子字符串与y所有的子字符串匹配,如果相同,那么就是一个公共子序列,然后求最长的一个。
建议观看上面的公开课,讲的非常好。本文思路是根据上面的公开课总结实践的。
一
我们先看看求一个字符串的所有子序列,有什么规律。比如给定一个字符串abc,那么有多少子序列呢?a b c ab ac bc abc还有一个空,就是2^3。按照上面公开课讲的非常通俗易懂,就是字符串一共有n个字符,那么每一位的字符都有两个状态----0-不是子序列的一员 1-是子序列的一员。那么总共的种类就是2^n种。这是最坏的情况,字符串中没有相同的字符,如果有,结果会比这个少。但是计算就是这么计算的。
了解了上面,那么我们进一步判断,如果给定一个x的子序列x1,那么怎么判断y中是否含有呢?简单的方法就是从x1的起始位置和y的起始位置开始判断,如果相同,每个索引加一,直到x1/y的字符串判断结束。如果不匹配,那么y索引加一,再从x1的开头开始计算。
这种是穷举法,肯定能得到结果,但是时间和空间都是最差的。我们先实现看看(穷举法排列组合可以参考排列组合)
struct MNODE
{
string substr;
MNODE* pnext;
MNODE()
{
pnext = nullptr;
}
};
MNODE* msubstr(string& srcstr, int index, int sublen)
{
MNODE* tmpp = nullptr;
MNODE* prep = nullptr;
if (index >= sublen && sublen > 0)
{
if (sublen == 1)
{
for (int i = 0; i < index; i++)
{
MNODE* ftpn = nullptr;
if (tmpp == nullptr)
{
tmpp = new MNODE;
prep = tmpp;
ftpn = tmpp;
}
else
{
ftpn = new MNODE;
prep->pnext = ftpn;
prep = ftpn;
}
ftpn->substr = srcstr[i];
}
}
else if (sublen > 1)
{
MNODE* nsub = msubstr(srcstr, index - 1, sublen

博客探讨了如何使用动态规划解决寻找两个字符串的最长公共子序列问题。介绍了从穷举法到动态规划的优化过程,包括推导公式和动态规划的特性。并通过实例展示了动态规划矩阵解法的直观性和效率。
最低0.47元/天 解锁文章
3478

被折叠的 条评论
为什么被折叠?



