动态规划(二)

        由算法 LCSLength 计算得到的数组 b 可用于快速构造序列X={x1,x2,…,xm}和Y={y1,y2,...,yn}的最长公共子序列。首先从b[m][n]开始,依其值在数组b中搜索。当在b[i][j]=1时,时,表示Xi和Yj的最长公共子序列是由Xi-1和Yj-1的最长公共子序列在尾部加上xi所得到
的子序列。当b[i][j]=2时,表示Xi和Yi和的最长公共子序列与Xi-1和Yj的最长公共子序列相
同。当b[i][j]=3时,表示Xi和Yi的最长公共子序列与Xi和Yj-1的最长公共子序列相同。


        下面的算法 LCS 实现根据 b的内容打印出Xi和Yj,和的最长公共子序列。通过算法调用
LCS(m,n,x,b)便可打印出序列X和Y的最长公共子序列。

#include<stdio.h>
#include<string.h>
int c[200][200];
int b[200][200];
char f[200];
int Max(int m,int n,int i,int j)
{
    if(m > n)
    {
        b[i][j] = -1;
        return m;
    }
    else
    {
        b[i][j] = 1;
        return n;
    }
}
void print(int i,int j,int s,char x[],char y[])
{
    if(b[i][j] == 0)
    {
        f[s-1] = x[i-1];
        i--;j--;s--;
        print(i,j,s,x,y);
    }
    else if(b[i][j] == -1)
    {
        i--;
        print(i,j,s,x,y);
    }
    else if(b[i][j] == 1)
    {
        j--;
        print(i,j,s,x,y);
    }
}
int LCS(char x[],char y[])
{
    int i,j;
    int x_len,y_len;
    x_len = strlen(x);
    y_len = strlen(y);
    printf("   ");
    for(i = 0;i < y_len;i++)
    {
        printf("%c  ",y[i]);
    }
    printf("\n");
    for(i = 1;i <= x_len;i++)
    {
        printf("%c  ",x[i-1]);
        for(j = 1;j <= y_len;j++)
        {
            if(x[i-1] == y[j-1])
            {
                c[i][j] = c[i-1][j-1] +1;
                b[i][j] = 0;
                printf("%d  ",c[i][j]);
            }
            else
            {
                c[i][j] = Max(c[i-1][j],c[i][j-1],i,j);
                printf("%d  ",c[i][j]);
            }
        }
        printf("\n");
    }
    //打印X和Y的LCS
    printf("X和Y的LCS是:");
    print(x_len,y_len,c[x_len][y_len],x,y);
    printf("%s",f);
    printf("\n");
    return c[x_len][y_len];
}
int main()
{
    char X[200],Y[200];
    int i,j,s;
    printf("请输入字符串X:");
    scanf("%s",X);
    printf("请输入字符串Y:");
    scanf("%s",Y);
    s = LCS(X,Y);
    printf("X和Y的LCS: %d \n",s);
}

        在算法LCS中,每次递归调用使i或j减1,因此算法的计算时间为O(m+n)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值