LCS最长公共子序列采取动态规划可以很好的解决。
通常是求解长度,若需要求解最长公共子序列。
那么采取root[][]数组记录 dp[][]表示前i部分、前j部分最长公共子序列长度
对于两个数组 arr1 arr2
若arr1[i]==arr2[j] 则dp[i+1][j+1]=dp[i][j]+1; root[i+1][j+1]=1;//表示沿着对角线回溯
否则,dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]) root[i+1][j+1]=2或者3 表示沿着左边或者上方回溯
//求解arr1 arr2的最长公共子序列
//初始化
for(int i=0;i<size;i++)
{
dp1[i][0]=0;
dp1[0][i]=0;
}
for(int i=0;i<size;i++)
for(int j=0;j<size;j++)
{
if(arr1[i]==arr[j]) //相等
{
dp1[i+1][j+1]=dp1[i][j]+1;
root[i+1][j+1]=1;//对角线回溯
}
else //i j处不相等
{
if(dp1[i][j+1]>dp1[i+1][j]) //相等的情况 也是往i小的位置回溯
{
dp1[i+1][j+1]=dp1[i][j+1];
root[i+1][j+1]=2;//上方回溯
}
else if(dp1[i][j+1]<=dp1[i+1][j])
{
dp1[i+1][j+1]=dp1[i+1][j];
root[i+1][j+1]=3;//左方回溯
}
}
}
回溯过程,从矩阵右下角开始,
vector<int> res;
for(int i=size,j=size;i>=1&&j>=1;)
{
if(root[i][j]==1) //沿着对角线回溯
{
res.push_back(arr[i-1]);
i--;
j--;
}
else if(root[i][j]==2) //沿着上方回溯
{
i--;
}
else
{
j--;
}
}
reverse(res.begin(),res.end());//翻转输出
return res;
否则其他情况 沿着左边或者上方回溯