hdu String (最长公共子序列)

Sample Input
  
  
2 aaaaa aaaa aa abcdef acebdf cf
 

Sample Output
  
  
Case #1: 4 Case #2: 3
题意: 有三个字符串A, B, C。 求串D。
D是A, B的公共子序列。
C是D的子串。
求最长的D串.输出长度.
dp[i][j] 表示 A的前i-1, B-1的前j的最长公共子序列。
dp1[i][j] 表示 A的后i+1, B+1的后j的最长公共子序列。
假设C在A, B中匹配的头尾位置是  ai, aj, bi, bj;
ans = max(ans,  dp[ai ][bi] + dp1[aj ][bj ] + strlen(C) );
暴力求出  C与A, B的所有匹配的  ai, aj, ai, bj
这里要预处理出 dp .
#include<stdio.h> #include<algorithm> using namespace std; #include<string.h> #define N 1005 char a[N]; char b[N]; char c[N]; int tsa[N]; int tea[N]; int tsb[N]; int teb[N]; struct node {     int s;     int e; } ansa[N],ansb[N]; int dp1[N][N],dp2[N][N]; int la,lb,lc; char transa[N],transb[N]; void LCS() {     memset(dp1,0,sizeof(dp1));     for(int i=1; i<=la; i++)     {         for(int j=1; j<=lb; j++)         {             if(a[i-1]==b[j-1])                 dp1[i][j]=dp1[i-1][j-1]+1;             else                 dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1]);         }     }     memset(dp2,0,sizeof(dp2));     int j=0;     for(int i=la-1;i>=0;i--)         transa[j++]=a[i];     j=0;     for(int i=lb-1;i>=0;i--)     transb[j++]=b[i];     for(int i=1; i<=la; i++)     {         //printf("aa.e=%d %d\n",aa.e,la);         for(int j=1; j<=lb; j++)         {             if(transa[i-1]==transb[j-1])                 dp2[i][j]=dp2[i-1][j-1]+1;             else                 dp2[i][j]=max(dp2[i-1][j],dp2[i][j-1]);         }     } } int main() {     int t,cas=0;     scanf("%d",&t);     while(t--)     {         cas++;         int maxx=-999999;         memset(a,0,sizeof(a));         memset(b,0,sizeof(b));         scanf("%s%s%s",a,b,c);         lc=strlen(c);         la=strlen(a);         lb=strlen(b);         int ta=0,tb=0,k;         for(int i=0;i<la;i++)         {             if(a[i]==c[0])             {                  k=1;                  int flag=0;                  for(int j=i+1;j<la;j++)                  {                      if(a[j]==c[k])                      k++;                      if(k==lc)                      {                          flag=j;                          break;                      }                  }                  if(flag!=0)                  {                      ansa[ta].s=i; //枚举c串在a串的首尾位子                      ansa[ta++].e=flag;                  }             }         }        for(int i=0;i<lb;i++)         {             if(b[i]==c[0])             {                  k=1;                  int flag=0;                  for(int j=i+1;j<lb;j++)                  {                      if(b[j]==c[k])                      k++;                      if(k==lc)                      {                          flag=j;                          break;                      }                  }                  if(flag!=0)                  {                      ansb[tb].s=i;                      ansb[tb++].e=flag;                  }             }         }         LCS();         for(int i=0; i<ta; i++)         {             for(int j=0; j<tb; j++)             {                 //printf("**%d %d %d %d\n",ansa[i].s,ansa[i].e,ansb[j].s,ansb[j].e);                 //DP(ansa[i],ansb[j]);                 maxx=max(maxx,dp1[ansa[i].s][ansb[j].s]+dp2[la-1-ansa[i].e][lb-1-ansb[j].e]);             }         }         printf("Case #%d: %d\n",cas,maxx+lc);     }     return 0; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值