HLBU 2029: 最长公共子序列

http://42.96.145.57/JudgeOnline/problem.php?id=2029

题目描述

字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。

输入

两个字符串

输出

最长公共子序列的长度

最长公共子序列

样例输入

ABCBDAB BDCABA

样例输出

4 BCBA

 输出那一快花了挺长时间,这道题有好多细节需要想清楚

该题动态规划公式:

做这题参考了这篇文章,http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html,写的不错,还有图解,不过代码不是C或者C++。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define maxSize 1000
 7 char str1[maxSize], str2[maxSize];
 8 int mem[maxSize][maxSize]; //用于输出最长子序列的回溯矩阵
 9 
10 //回溯输出最长子序列
11 void print(int m[][maxSize], char *str1, int i, int j)
12 {
13     if(i==0||j==0) return;
14     if(m[i][j]==0)
15     {
16         print(m, str1, i-1, j-1);
17         cout<<str1[i-1];  //输出放在print之后正序输出,放在print之前逆序输出
18     }
19     else if(m[i][j]==-1)
20     {
21         print(m, str1, i, j-1);
22     }
23     else
24     {
25         print(m, str1, i-1, j);
26     }
27 }
28 
29 int main()
30 {
31     while(cin>>str1>>str2)
32     {
33         int len1 = strlen(str1);
34         int len2 = strlen(str2);
35         int dp[len1+1][len2+1];
36         memset(dp, 0, sizeof(dp));
37         memset(mem, 0, sizeof(mem));
38         for(int i=1; i<=len1; i++)
39         {
40             for(int j=1; j<=len2 ;j++)
41             {
42                 if(str1[i-1]==str2[j-1])
43                 {
44                     dp[i][j] = dp[i-1][j-1]+1;
45                     mem[i][j]=0;//向左上走
46                 }
47                 //如果有多个长度相同的最长子序列,优先向上走,则得到字符串1其中的第一个,否则得到字符串1中的走后一个
48                 else if(dp[i-1][j] >= dp[i][j-1] )
49                 {
50                      dp[i][j] = dp[i-1][j];
51                     mem[i][j] = 1;//向上走
52                 }
53                 else
54                 {
55                     dp[i][j] = dp[i][j-1];
56                     mem[i][j] = -1; //向左走
57                 }
58             }
59         }
60 
61 /********打印回溯矩阵******
62         for(int i=0; i<=len1; i++)
63         {
64             for(int j=0; j<=len2 ;j++)
65             {
66                 cout<<mem[i][j]<<" ";
67             }
68             cout<<endl;
69         }
70 *************************/
71 
72         cout<<dp[len1][len2]<<endl;
73         print(mem, str1, len1, len2);
74         cout<<endl;
75     }
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/rorchach/archive/2013/03/22/2975257.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值