问题描述:
给定两个字符串,求解这两个字符串的最长公共子序列。如:S1={1,5,2,8,9,3,6},S2={5,6,8,9,3,7},其最长公共子序列为{5,8,9,3},最长公共子序列长度为4。
最优子结构性质分析:
设序列S1={x1,x2,…,xn}和S2={y1,y2,…,ym}的最长公共子序列为S={z1, z2,…, zk} ,则
1)若xn=ym ,那么 zk=xn=ym 且 S[k-1]是S1[n-1] 和 S2[m-1]的最长公共子序列;
2)若xn≠ym 且 zk≠xn 则 S[k]是S1[n-1]和 S2[m]的最长公共子序列;
3)若xn≠ym 且 zk≠ym 则 S[k]是S1[n]和 S2[m-1] 的最长公共子序列。
由此可见,两个序列的最长公共子序列包含了这两个序列的前缀的最长公共子序列。因此,最长公共子序列问题具有最优子结构性质,可以用动态规划求解。
建立递归关系:
dp[i][j]表示:S1的前i个字符和S2的前j个字符的最长公共子序列长度。
自底向上求解最优值:
if(S1[i]==S2[j]) “↖” 用1代表
if(dp[i-1][j]>dp[i][j-1]) “↑” 用2代表
if(dp[i-1][j]<=dp[i][j-1]) “←” 用3代表
时间复杂度:O(nm)。
根据计算最优值时得到的信息,构造最优解:
时间复杂度:O(n+m)。
完整代码
#include <iostream>
using namespace std;
#define N 100
int n,m;
char S1[N],S2[N];
int dp[N][N];
int b[N][N];
void LCSLength()
{
for(int i=0;i<=n;i++)
for(int j=0