LCS最大公共序列,即A,B字符串中的最大公共部分,可以是不连续的。
这块代码分为两部分,两部分的时间复杂度是一样的,都是O(N*N),空间复杂度有不同
假设dij为A字符串取i个字符,B字符串取j个字符后对应俩字符串的LCS的长度。
那么:
当i=0或者j=0的时候,显然dij=0;
i!=0且j!=0,并且a[i]=b[j],此时dij=d(i-1)(j-1)+1;
i!=0且j!=0,并且a[i]!=b[j],此时dij=max(di(j-1),d(i-1)j).此即为LCS的DP公式。
据此可以写出代码:
int LCS()
{
for(int i =1;i<=LEN1;++i)
for(int j =1;j<=LEN2;++j)
{
if(a[i-1] == b[j-1])
d[i][j] = 1+d[i-1][j-1];
else
{
d[i][j] = d[i-1][j]>d[i][j-1]?d[i-1][j]:d[i][j-1];
}
cout<<"<i,j>"<<i<<" "<<j<<" "<<d[i][j]<<endl;
}
return d[LEN1][LEN2];
}
另外,可以看出,对i进行循环时,j已经进行了轮次循环。
换句话说,i=2时,i=0的对应的d[i][j]已经是用不到了;i=3时,i=1对应的d[i][j]已经是用不到了。
这个时候可以把dN*N矩阵缩小为DN*2.循环使用两列,空间复杂度为O(2N)。
对应代码为
int LCS2()
{
int k;
for(int i =1;i<=LEN1;++i)
for(int j =1;j<=LEN2;++j)
{
k = i&1;
if(a[i-1] == b[j-1])
d[k][j] = 1+d[k^1][j-1];
else
{
d[k][j] = d[k^1][j]>d[k][j-1]?d[k^1][j]:d[k][j-1];
}
cout<<"<i,j>"<<i<<" "<<j<<" "<<d[k][j]<<endl;
}
return d[k][LEN2];
}