HDU-1159 -Common Subsequence

Common Subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 36329    Accepted Submission(s): 16631


Problem Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.
 

Sample Input
      
      
abcfbc abfcab programming contest abcd mnp
 

Sample Output
      
      
4 2 0
 

Source
 

Recommend
Ignatius

这道题也是简单的DP 
我觉得DP最重要还是思路,因为代码很短的,很好实现,但是方法很难想
如果DP都能想出状态转移方程,那就NB了
(1)大部分DP的思路就是如何找最优解,并更新最优解
这题的思路就是,如果发现有相同的字母,那么就更新最优解,
那么从哪里更新最优解那? 当然从上一次的dp中更新就是 dp【i-1】【j-1】
这是算前dp【i-1】【j-1】是前i -1个字母的最优解,那么就在这上面加1
还有,没一个字母只能对应一个字母,不能多对一,那么你还要排重
(2)如果没发现相同的字母,还是要找最优解,从map[i-1][j-1],map[i-1][j],map[i][j-1]中找最大的
那么为什么要从这3个中找最大的那?
其实这三个数都表示上一步的最优解 为了容易区分我  先输入的字符串为s1  后输入的为s2
dp[i-1][j-1]其实是 输入s1第  i-1个字符  并比较到 s2 第 j-1 个字符的最优解
dp[i-1][j]  其实是输入 s1第 i-1个字符,并比较到 s2第j个字符的最优解
dp[i][j-1] 其实是输入s1第i个字符,并比较到s2第 j-1 个字符的最优解
(3)上面这段话看不懂,没关系,简单来说;
把两个字符串比较,看成s1输入一个字符比较,然后s2再输入一个字符,再比较,然后s1再输入第二个字符,同理s2
每输入一次,就要比较一下,找出当前的最优解,这三个最优解分别表示当前解的前三次dp,找出最优的
那推理一下,其实我只要找连个就行了,对的,其实只要找map[i][j-1]和map[i-1][j];
注意,只找前1个会WA的
     a    b     e                             a      e      f
a   1   1     1                       a    1      1      1
e   1   1     2                       b     1     1      1
 f    1  1     2                       e     1      2      2
可以配合这个表看一下,这就是打表出的结果
一组数据调换一下顺序,就可以看出为什么要至少找两个,还要找这两个的原因

下面上代码

#include<stdio.h>
#include<string.h>
char a[1000],b[1000];
int map[1000][1000];
int max(int a,int b)
{
    if(a>=b)
        return a;
    else
        return b;
}
int main()
{
    int len1,len2,pos=1,flag=0;
    while(scanf("%s%s",a,b)!=EOF)
    {
        int num=-1;
        len1=strlen(a);
        len2=strlen(b);
        memset(map,0,sizeof(map));
        for(int i=1; i<=len1; i++)
        {
            for(int j=pos; j<=len2; j++)
            {
                flag=0;
                if(a[i-1]==b[j-1]&&flag==0)
                {
                    map[i][j]=map[i-1][j-1]+1;
                    flag=1;
                }
                else
                {
                    map[i][j]=max(map[i][j-1],map[i-1][j]);
                }
                if(map[i][j]>num)
                {
                    num=map[i][j];
                }
            }
            /*for(int k=1;k<=len2;k++)     //²âÊÔÊý¾Ý
            {
                printf("%d ",map[i][k]);
            }
            printf("\n");*/
        }
        printf("%d\n",map[len1][len2]);
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值