现在的位置: 首页 > 综合 > 正文

hdu 4681 String/杭电多校第八场1006 最长公共子序列长

2014年11月23日 ⁄ 综合 ⁄ 共 1437字 ⁄ 字号 评论关闭
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 1111
char a[maxn],b[maxn],c[maxn];
int dp1[maxn][maxn],dp2[maxn][maxn],n,m,len;
struct node//记录在字符串a,b中,c串的首尾位置
{
    int x,y;
};
void lcs()//求最长公共子序列长
{
    int i, j,k;
    //从字符串左到右
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        if(a[i]==b[j])
            dp1[i+1][j+1]=dp1[i][j]+1;
        else
            dp1[i+1][j+1]=max(dp1[i][j+1],dp1[i+1][j]);
    //从字符串右到左
    for(i=n-1;i>=0;i--)
        for(j=m-1;j>=0;j--)
        if(a[i]==b[j])
            dp2[i+1][j+1]=dp2[i+2][j+2]+1;
        else
            dp2[i+1][j+1]=max(dp2[i+1][j+2],dp2[i+2][j+1]);
}
void find(char str[],int n,int &t,node e[])//找到c串在a,b中的首尾位置
{
    int i,j,k;
    for(i=0;i<n;i++)
    {
        if(str[i]==c[0])
        {
            for(j=i+1,k=1;j<n;j++)
            {
                if(str[j]==c[k])k++;
                if(k==len)break;
            }
            if(k==len){e[t].x=i+1;e[t++].y=j+1;}
            else break;
        }
    }
}
int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        int i,j,k;
        scanf("%s%s%s",a,b,c);
        n=strlen(a);
        m=strlen(b);
        len=strlen(c);
        lcs();
        int ans,num1,num2;
        node e[maxn],f[maxn];
        ans=num1=num2=0;
        find(a,n,num1,e);
        find(b,m,num2,f);
        for(i=0;i<num1;i++)
            for(j=0;j<num2;j++)
            ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]);
        printf("Case #%d: %d\n",++tt,ans+len);
    }
    return 0;
}
/*
    先求出a,b的最长公共子序列,从开头和末尾开始的都要
    其中dp1[i][j]表示a中第i个字符之前,b中第j个字符之前的最长公共子序列长
    dp2[i][j]表示a中第i个字符之后,b中第j个字符之后的最长公共子序列长
    
    用find找到a中所有c首尾所在位置,在首位置固定的情况下找到末位置最小的即可,因为更长的会使结果值较小,存在结构体重
    同理找到b的
    
    e[i].x,e[i].y,f[j].x,f[j].y
    那么d最长为ans=max(ans,dp1[e[i].x-1][f[j].x-1]+dp2[e[i].y+1][f[j].y+1]+len),
就是说包含c的部分已经固定,只要加上之前和之后的最长公共子序列长就好了
*/

抱歉!评论已关闭.