最长公共子序列

前段时间我写过最长递增子序列,我们用到的是动态规划的思想,今天谈的最长公共子序列仍然是动态规划的一个十分重要的一部分。结合算法导论的讲解,谈谈我自己的理解。求解的关键是描述的过程,先引进一个定理:

(lcs最优子结构)设x=(x1,x2,……,xm)和y=(y1,y2,……,yn)为两个序列,并设z=(z1,z2……,zk)为x和y的任意一个lcs.

1)如果xm=yn,那么zk=xm=yn而且zk-1是xm-1和yn-1的一个lcs;

2)如果xm!=yn,那么zk!=xm蕴含z是xm-1和y的一个lcs;

3)如果xm!=yn,那么zk!=yn蕴含z是x和yn-1的一个lcs;

关于证明的过程,我就滤过了,那么关键是我们知道了这个定理,我们就应该遵循动态规划的第二个步骤了,找递归解,根据定理,我们很容易的找到了递归解,既:

c[i][j]=    1) 0                                        如果i=0,j=0;

                2)c[i-1][j-1]+1                       如果i>0,j>0和xi=yj

                3)max(c[i][j-1],c[i-1][j])        如果i,j>0和xi!=yj

 

从而剩下的就是写代码了,代码是自己写的,如果有哪些不对的地方,欢迎拍砖!!!

C语言: Codee#13001
//******************************************************
//题目:最长公共子序列
//by dashan1990
//完成时间:2010,8
//完成状态:已完成。
//*******************************************************
#include <stdio.h>
#include <string.h>
#define MAX 100
int a [ MAX ],b [ MAX ];
int c [ MAX ][ MAX ];
int n , m;
int LCS_lenght()
{
    int i , j;
    for( i = 0; i <n; i ++)
    {
        c [ i ][ 0 ] = 0;
        c [ 0 ][ i ] = 0;
    }
    for( i = 0; i <n; i ++)
    {
        for( j = 0; j < m; j ++)
        {
            if( a [ i ] ==b [ j ])
            {
                c [ i ][ j ] = c [ i - 1 ][ j - 1 ] + 1;
            }
            else if( c [ i - 1 ][ j ] >= c [ i ][ j - 1 ] && a [ i ] !=b [ j ])
            {
                c [ i ][ j ] = c [ i - 1 ][ j ];
            }
            else if( a [ i ] !=b [ j ] && c [ i - 1 ][ j ] < c [ i ][ j - 1 ])
            {
                c [ i ][ j ] = c [ i ][ j - 1 ];
            }
        }
    }
    return c [n - 1 ][ m - 1 ];
}
int main()
{
    int i , j;
    int w;
    while( scanf( "%d%d" , &n , & m))
    {
        for( i = 0; i <n; i ++)
        {
            scanf( "%d" , a + i);
        }
        for( i = 0; i < m; i ++)
        {
            scanf( "%d" , &b [ i ]);
        }
        w = LCS_lenght();
        printf( "%d" , w);
        putchar( '/n');
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值