版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HackQ_sxj/article/details/80572772
问题描述:给定两个序列X={B,C,D,A},Y={A,B,C,B},请采用动态规划策略求出其最长公共子序列,要求给出过程。
解题思想:设序列X={x1,x2,...,xm}和Y={x1,x2,...,xn}的最长公共子序列Z={z1,z2,...,zk}则
*若xm=yn,则zk = xm = yn,且Zk-1是 Xm-1和Yn-1的最长公共子序列。
*若xm≠yn,且zk≠xm,则Z是Xm-1和Y的最长公共子序列。
*若xm≠yn,且zk≠yn,则Z是X和Yn-1的最长公共子序列。
子问题的递归结构:用c[i][j]记录序列Xi和Yj的最长公共子序列的长度,则
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
void LCSLength(int m, int n, char *x, char *y, int **c, int **b)
{
int i, j;
for(i = 0; i <= m; i++) c[i][0] = 0;
for(i = 0; i <= n; i++) c[0][i] = 0;
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
{
if(x[i-1] == y[j-1])
{
c[i][j] = c[i-1][j-1]+1;
b[i][j] = 0;
}
else if(c[i-1][j] >= c[i][j-1])
{
c[i][j] = c[i-1][j];
b[i][j] = 1;
}
else{
c[i][j] = c[i][j-1];
b[i][j] = -1;
}
}
cout<<c[m][n]<<endl;
}
void LCS(int i, int j, char *x, int **b)
{
if(i == 0||j == 0) return;
if(b[i][j] == 0)
{
LCS(i-1, j-1, x, b);
cout << x[i-1];
}
else if(b[i][j] == 1)
LCS(i-1, j, x, b);
else
LCS(i, j-1, x, b);
}
int main(){
char x[100], y[100];
int i, m, n, len;
printf("请输入第一个字符串:\n");
gets(x);
printf("请输入第二个字符串:\n");
gets(y);
m = strlen(x);
n = strlen(y);
// cout << x<<" "<<y<<" "<<m<<" "<<n<<" ";
int **c = new int*[m+1];
int **b = new int*[n+1];
for (int i = 0; i < m+1; i++)
{
c[i] = new int[m+1];
}
for (int i = 0; i < n+1; i++)
{
b[i] = new int[n+1];
}
cout<<"最长公共子序列的长度为:";
LCSLength(m, n, x, y, c, b);
cout<<"最长公共子序列为:"<<endl;
LCS(m, n, x, b);
cout<<endl;
for (int i = 0; i < m+1; i++)
{
delete[] c[i];
}
for (int i = 0; i < n+1; i++)
{
delete[] b[i];
}
delete[]c;
delete[]b;
return 0;
}
结果: