上一篇文章对于动态规划的学习以及算法实现均没有问题,在这里再补充一点,可能之前没有表述的更加清晰,在此借鉴一位博客文章在此简述一下:
第一步依旧是递推关系式的推导,根据关系逻辑编写代码打印出标记二维数组如图:
构造出此图之后,对于他的构造子串的输出,是按倒序一步步从后往前查找过去的,如图箭头所示;也正如程序中所描述的分别为i-1,j-1一步步到0为止。
在这里还有一种计算方法,虽然费时耗力但是也是一种解决问题的方法,且让我们比较一下他们的异同,以便遇到问题时可以想到更多的解决、优化方法。
穷举法:两个字符串依次对每一个字符对比比较,取得的所有子串再取最大者。思想如下:
1.若a[i]==b[j],则此字符加入子串,i++,j++
2.若a[i]!=b[j],此时有2种处理情况:1)a[i++]与b[j]比较 ;2)a[i]与b[j++]比较;
算法如下:
void LCS(string str1, string str2, string lcs)
{
if(str1.length() == 0 || str2.length() == 0)
return;
if(str1[0] == str2[0])
{
lcs += str1[0];
LCS(str1.substr(1), str2.substr(1), lcs);
}
else
{
string strTmp1,strTmp2;
LCS(str1.substr(1), str2, strTmp1); //后移str1
LCS(str1, str2.substr(1), strTmp2); //后移str2
lcs += GetLongest(strTmp1, strTmp2);
}
}
两者都是利用的递归调用,不同的是第二种方法对于str1的每个字符与str2的每个字符每次都是意义比较然后连接再取大,而第一种方法只要是前面比对过了则利用标记记录下比对结果以供后面程序直接判断不需再次重复计算;对于遇到同样的可能包含大量重复问题的时候,我们应该有所启发借鉴;
记得当时面试的时候遇到过一个同样的问题,当时用的双重for循环,辅以标记位用于输出,面试官研究了一大会儿非说程序有问题但也没指出来哪里有问题,可能一看我用的不是动态规划心里就直接pass掉了吧。有时间再拿出来研究一下!