最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
动态规划的一个计算两个序列的最长公共子序列的方法如下:
以两个序列 X、Y 为例子: 设有二维数组 f[i,j] 表示 X 的 i 位和 Y 的 j 位之前的最长公共子序列的长度,则有: f[1][1] = same(1,1); f[i,j] = max{f[i-1][j -1] + same(i,j),f[i-1,j],f[i,j-1]} 其中,same(a,b)当 X 的第 a 位与 Y 的第 b 位完全相同时为“1”,否则为“0”。 此时,f[j]中最大的数便是 X 和 Y 的最长公共子序列的长度,依据该数组回溯,便可找出最长公共子序列。 该算法的空间、时间复杂度均为O(n^2),经过优化后,空间复杂度可为O(n)。#include<iostream>
#include<string>
using namespace std;
#define N 50
int Max(int a,int b)
{
if(a>=b)
return a;
return b;
}
/* 空间O(m*n)
int LCS(char st1[N],char st2[N])
{
//计算字符串长度
int na,nb;
na=strlen(st1);
nb=strlen(st2);
//计数矩阵
int c[N][N];
for(int i=0;i<=na;i++)
c[i][0]=0;
for(int j=0;j<=nb;j++)
c[j][0]=0;
//动态规划
for(int i=0;i<=na;i++)
for(int j=0;j<=nb;j++)
{
if(st1[i]==st2[j])
c[i+1][j+1]=c[i][j]+1;
else
c[i+1][j+1]=Max(c[i][j+1],c[i+1][j]);
}
cout<<c[na][nb]<<endl;
return c[na][nb];
}
*/
//优化空间版O(n)
int LCS(char st1[N],char st2[N])
{
//计算字符串长度
int na,nb;
int tag=1;
na=strlen(st1);
nb=strlen(st2);
//计数矩阵
int c[2][N];
for(int j=0;j<=nb;j++)
c[0][j]=0;
c[1][0]=0;
//动态规划
for(int i=1;i<=na;i++)
{
for(int j=1;j<=nb;j++)
{
if(st1[i-1]==st2[j-1])
c[tag][j]=c[1-tag][j-1]+1;
else
c[tag][j]=Max(c[tag][j-1],c[1-tag][j]);
}
tag=1-tag;
}
cout<<c[1-tag][nb]<<endl;
return c[1-tag][nb];
}
int main()
{
char a[N],b[N];
cin>>a;
cin>>b;
LCS(a,b);
return 0;
}