<1> 子序列:就是在原序列中找出一部分组成的序列。 例:字符串“abcdefg” 的子序列有 “ac”、“ade”....一共有27个子序列。
<2> 最长公共子序列:一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。例:字符串“cnblogs”和“belong”的最长公共子序列为“blog”。
<3> 子串:串中任意个连续的字符组成的子序列称为该串的子串
<4> 最长公共子串:两个字符串中,最长的相同子字符串的长度(也是要求字串连续)
最长公共子串和最长公共子序列的区别:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;
也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。
解决方法:动态规划算法
用c[i,j]记录序列Xi和Yj的最长公共子序列的长度,其中Xi=,Yj=。当i = 0或j = 0时,空序列是Xi和Yj的最长公共子序列,故c[i,j] = 0。其他情况下,可得递归关系如下所示:
由算法LCS_LENGTH和LCS计算出的结果如下图所示:
在序列X={A,B,C,B,D,A,B}和 Y={B,D,C,A,B,A}上,由LCS_LENGTH计算出的表c和b。第i行和第j列中的方块包含了c[i,j]的值以及指向b[i,j]的箭头。在c[7,6]的项4,表的右下角为X和Y的一个LCS的长度。对于i,j>0,项c[i,j]仅依赖于是否有xi=yi,及项c[i-1,j]和c[i,j-1]的值,这几个项都在c[i,j]之前计算。为了重构一个LCS的元素,从右下角开始跟踪b[i,j]的箭头即可,这条路径标示为阴影,这条路径上的每一个“↖”对应于一个使xi=yi为一个LCS的成员的项(高亮标示)。
for(i=1; i<=len1; i++)
for(j=1; j<=len2; j++)
{
if(str1[i-1] ==str2[j-1])
c[i][j] = c[i-1][j-1]+1;//当str1[i-1] ==str2[j-1]相等时, 直接在上一个最长子序列上加1;
else
c[i][j] = max(c[i][j-1],c[i-1][j]);//当str1[i-1] !=str2[j-1]相等时,找出 c[i][j-1],c[i-1][j]中谁最大;
}