LCS之poj1080

最长公共子序列(lcs)是dp的一块重要内容,求两段字符串的最大公共长度。

如下是模板代码:

               for (int i = 1; i <= str1.Length; i++)
                        for (int j = 1; j <= str2.Length; j++)
                         {
                                  //相等的情况
                                  if (str1[i - 1] == str2[j - 1])
                                             martix[i, j] = martix[i - 1, j - 1] + 1;
                                   else
                                   {
                                              //比较“左边”和“上边“,根据其max来填充
                                              if (martix[i - 1, j] >= martix[i, j - 1])
                                                          martix[i, j] = martix[i - 1, j];
                                               else
                                                          martix[i, j] = martix[i, j - 1];
                                    }
                           }


poj1080

题目大意:给定t的案例。一个案例给定两个字符串的长度,和字符串,只含有’A‘C’G‘T’-‘五个字符。并且给出每两个字符所代表的数字。要求在不改变最大长度的情况下,求出两个字符串匹配之后的最大数。(可在较短字符串内添加字符‘-’)


思路如下:

  字符串取str1[i] str2[j]时有以下三种情况
          1:str1[i]~~'-'         即temp1=map[i-1][j]+data[str1[i]]['-']
          2:  ‘-’~~str2[j]         即temp2=map[i][j-1]+data[str2[j]]['-']
          3: str1[i]~~str2[j]    即temp3=map[i][j]+data[str1[i-1]][str2[j-1]]
      综上所述 map[i][j]=max(temp1,temp2,temp3)
                        此时,map[aa][bb]即为最大的数。




代码如下:

#include<stdio.h>
#include<string.h>
int map[105][105],aa,bb;
char a[105],b[105];
int data[10][10]={{5,-1,-2,-1,-3},{-1,5,-3,-2,-4},{-2,-3,5,-2,-2},
                  {-1,-2,-2,5,-1},{-3,-4,-2,-1,0}};

int get_id(char p)      //得到每个字符对应的序号
{
     switch(p)
     {
          case 'A': return 0;
          case 'C': return 1;
          case 'G': return 2;
          case 'T': return 3;
          case '-': return 4;
     }
}

int MAX(int a,int b,int c)    //取三个数中的最大数
{
     int k;
     k=a>b? a:b;
     k=k>c? k:c;
     return k;
}



void Work()                      
{
     int i,j;
     map[0][0]=0;                 //初始化
     for(i=1;i<=aa;i++)
          map[i][0]=data[get_id(a[i])][get_id('-')]+map[i-1][0];
     for(j=1;j<=bb;j++)
          map[0][j]=data[get_id(b[j])][get_id('-')]+map[0][j-1];
     for(i=1;i<=aa;i++)            //dp部分
        for(j=1;j<=bb;j++)
        {
           int temp1=map[i-1][j-1]+data[get_id(a[i])][get_id(b[j])];
           int temp2=map[i-1][j]+data[get_id(a[i])][get_id('-')];
           int temp3=map[i][j-1]+data[get_id(b[j])][get_id('-')];
            map[i][j]=MAX(temp1,temp2,temp3);
        }
}



int main()
{
     int t;
     scanf("%d",&t);
     while(t--)
     {
          scanf("%d%s",&aa,a+1);
          scanf("%d%s",&bb,b+1);
          Work();
          printf("%d\n",map[aa][bb]);
     }
     return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值