公共子序列

 
【训练题】公共子序列
 
 
时间限制:1秒  内存限制:64M
 
   

 

 

 

 

【问题描述】

 

 



 

 

 

 

【输入格式】

 

 


  有两行,每一行为一个大写字母构成的长度不超过200的字符串,表示序列X和Y。

 

 

 

 

【输出格式】

 

 


  第一行为一个非负正整数,表示所求得的最长公共子序列的长度。

 

 

 

 

【输入样例】

 

 


ABCBDAB
BDCABA

 

 

 

 

【输出样例】

 

 


4

 

 

 

这是一道经典而又基础的区间动规题目。

看到题目,我们可以轻易的想到,如果A串的前i个与B串的前j个元素的最长公共子序列长度为x,又如果A[i+1]=B[j+1],那么A串的前i+1个与B串的前j+1个元素的最长公共子序列长度就为x+1;

那么状态转移方程的一部分就显而易见了 f(i,j)=f(i-1,j-1)+1  (A[i]=B[j])

那么如果A[i]!=B[i]的时候呢?我们想想,如果A串的前i-1个与B串的前j个元素的最长公共子序列长度为x,那么A串的前i个与B串的前j个元素的最长公共子序列长度至少都有x;如果A串的前i个与B串的前j-1个元素的最长公共子序列长度为y,那么A串的前i个与B串的前j个元素的最长公共子序列长度至少都有y

那么剩下一部的状态转移方程就出来了  f(i,j)=MAX{ f(i-1,j) , f(i,j-1) } (A[i]!=B[j])

有人会问,会不会f(i-1,j)或者f(i,j-1)比f(i-1,j-1)+1还大呢,这样在A[i]=B[j]时选择第二种方案岂不是更好?

这样的情况是不存在的,因为f(i-1,j)或者f(i,j-1)只会比f(i-1,j-1)大1个长度(想想为什么),所以f(i-1,j)或者f(i,j-1)不会比f(i-1,j-1)+1还大

 

边界 f(0,0)=0

   f(0,j)=0

   f(i,0)=0

最后答案:f(a,b);(a表示A的长度,b表示B的长度)

 

程序:

#include<iostream>
#include<cstdio>
#include<cstring>

#define f(i,j) d[(i)-1][(j)-1]

using namespace std;

char A[205],B[205];
int d[205][205];

void Ready()
{
 scanf("%s",A);
 scanf("%s",B);
 memset(d,0,sizeof(d));
}

int MAX(int x,int y)
{
 return x>y?x:y;
}

void Working()
{
 
 int a,b;
 a=strlen(A);
 b=strlen(B);
 if(A[0]==B[0])f(1,1)=1;
 for(int i=2;i<=a;i++)
  {
   f(i,1)=f(i-1,1);
   if(A[i-1]==B[0])f(i,1)=1;
  }
  for(int i=2;i<=b;i++)
  {
   f(1,i)=f(1,i-1);
   if(A[0]==B[i-1])f(1,i)=1;
  }

 for(int i=2;i<=a;i++)
  for(int j=2;j<=b;j++)
   {
    f(i,j)=MAX(f(i-1,j),f(i,j-1));
    if(A[i-1]==B[j-1])
     f(i,j)=MAX(f(i,j),f(i-1,j-1)+1);
   }
   printf("%d",f(a,b));
}

int main()
{
 Ready();
 Working();
 return 0;
}

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值