动态规划——最长公共子序列

描述
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1, x2,…, xm>,则另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, ik>,使得对于所有j=1,2,…,k有:

Xij = Zj

如果一个序列S即是A的子序列又是B的子序列,则称S是A、B的公共子序列。
求A、B所有公共子序列中最长的序列的长度。
 
输入
输入共两行,每行一个由字母和数字组成的字符串,代表序列A、B。A、B的长度不超过200个字符。
 
输出
一个整数,表示最长各个子序列的长度。
格式:printf("%d\n");
 
输入样例
programming
contest
 
输出样例
2

思路分析:动态规划问题具有最优子结构性质和子问题重叠性质。

a) 最长公共子序列的结构

若用穷举搜索法,耗时太长,算法需要指数时间。

易证最长公共子序列问题也有最优子结构性质

设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:

       i.             xm=yn,则zk=xm=ynZk-1Xm-1Yn-1的最长公共子序列;

      ii.             xm≠ynzk≠xmZXm-1Y的最长公共子序列;

    iii.             xm≠ynzk≠yn,则ZXYn-1的最长公共子序列。

其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。

最长公共子序列问题具有最优子结构性质

b) 子问题的递归结构

由最长公共子序列问题的最优子结构性质可知,要找出X=<x1,x2, …, xm>和Y=<y1, y2,…, yn>的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者即为X和Y的一个最长公共子序列。

由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。

我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=<x1,x2, …, xi>,Yj=<y1,y2, …, yj>。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。建立递归关系如下:



代码如下,已经经过测试。

#include <iostream>
#include <string.h>

using namespace std;
char x[200], y[200];
int num[201][201];
int get_length(char x[], char y[]);

int main()
{
  cin >> x >> y;
  //cout << x << y;


  cout << get_length(x, y) << endl;


}

int get_length(char x[], char y[])
{
    int n, m;
    n = strlen(x);
    m = strlen(y);

    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(x[i - 1] == y[j - 1])
                num[i][j] = num [i - 1][j - 1] + 1;
            else
            {
                if(num[i - 1][j] > num[i][j - 1])
                num[i][j] = num[i-1][j];
                else num[i][j] = num[i][j-1];
            }
        }
    }

    return num[n][m];

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值