动态规划(二.LCS)

这里写图片描述

用动态规划求最长公共子序列其实核心思想很简单,就是分3种情况判断,根据不同情况做相应递归调用即可。如上图3种情况:i,j分别表示字符串1、2的当前相对长度,s[i,j]表示字符串1的前i个字符与字符串2的前j个字符所拥有的最长公共子序列的长度;
第一种情况:很显然当i=0 || j=0时,s[i,j]==0;
第二种:当字符串1、2的第i、j个字符相等时,则c[i,j]的长度直接为s[i-1,j-1]+1;
第三种:也就是当字符串1、2的第i、j个字符不相等时,分别前推一个字符计算s[],并取较大者;
核心就是3种情况的判断及相应调用的处理;

#include<stdio.h>
#include<string>
using namespace std;

char c[20];  //记录子序列字符,便于输出lcs
int num=0;   //子序列个数,可能有多个lcs

//求最长公共子序列的长度
int lcs_Len(string x,string y,int b[20][20]){

    int len1=x.length();
    int len2=y.length();
    int s[20][20];  //存储:x前i个字符串与y前j个字符串对应的lcs
    int i,j;

    //情况一:
    for(i=0;i<=len1;i++)
        s[i][0]=0;
    for(j=0;j<=len2;j++)
        s[0][j]=0;

    for(i=1;i<=len1;i++)
        for(j=1;j<=len2;j++){
            if(x[i-1]==y[j-1]){
                s[i][j]=s[i-1][j-1]+1;//情况二
                b[i][j]=1;
            }
            else{  //情况3
                if(s[i-1][j]>s[i][j-1]){
                    s[i][j]=s[i-1][j];
                    b[i][j]=2;
                }
                else{
                    s[i][j]=s[i][j-1];
                    b[i][j]=3;
                }
            }

        }
    //代价矩阵表
    for(i=1;i<=len1;i++){
        for(j=1;j<=len2;j++){
            printf("%d ",s[i][j]);          
        }
        printf("\n");
    }
    return s[len1][len2];
}

//输出lcs
void lcs_Show(int i,int j,string x,int b[20][20],int len,int lcsLen){

    if(i==0 || j==0){  //情况一
        return;
    }
    if(b[i][j]==1){    //情况二
        c[len--]=x[i-1];
        lcs_Show(i-1,j-1,x,b,len,lcsLen);
    }else{       //情况三
        if(b[i][j]==2)
            lcs_Show(i-1,j,x,b,len,lcsLen);
        else
            lcs_Show(i,j-1,x,b,len,lcsLen);

    }
}
void main(){

    /*lcs test
        只实现了输出其中一个最长公共子序列   
     */
    string s1="ABCBDAB";
    string s2="BDCABA";

    int lcsLen;        //最长子序列长度
    int b[20][20];     //二维数组记录标记

    lcsLen=lcs_Len(s1,s2,b);

  //  printf("%d\n",lcsLen);
    lcs_Show(s1.length(),s2.length(),s1,b,lcsLen,lcsLen);

        for(int k=1;k<=lcsLen;k++)
            printf("%c",c[k]);//输出lcs
        printf("\n");
}

效果图:

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值