计算a、b字符串的不连续公共子串的长度(包含c字符串) -hdu4681

计算a、b字符串的不连续公共子串的长度(包含c字符串) ----hdu4681

题意:

给你字符串A,B,C,让你找一个字符串D,使得D串是A,B的字串,C串是D的连续字串。

做法:

找出C串在A,B串的位置。

对于每一个位置对,D串的长度为前一半的最长公共子序列+C串的长度+后一半的最长公共子序列



#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1005
#define Max(a,b) a>b?a:b
using namespace std;
int len1,len2,len3,num;
int dp1[N][N],dp2[N][N],pp[N<<2][2];
//dp1[][]表示字符串a,b从前往后的最大公共子串,dp2[][]表示字符串a,b从后往前的最大公共子串
//pp[][]记录字符串c在a,b中出现的第一个位置和最后一个位置
char a[N],b[N],c[N];
void solve(char *str,int n)
{
    int i,j,k;
    int l=strlen(str);
    for(i=0; i<=l-len3; i++)
        if(str[i]==c[0])
        {
            for(j=i,k=0; j<n&&k<len3; j++)
                if(str[j]==c[k])
                    k++;
            if(k==len3)
            {
                pp[num][0]=i+1;
                pp[num][1]=j;
                num++;
            }
            else break;
        }
}

int main()
{
    int i,j,T,Count=0;
    scanf("%d",&T);
    getchar();
    while(T--)
    {
        gets(a);
        len1=strlen(a);
        gets(b);
        len2=strlen(b);
        gets(c);
        len3=strlen(c);
        memset(dp1,0,sizeof(dp1));
        for(i=1; i<=len1; i++)
            for(j=1; j<=len2; 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));
        for(i=len1; i>=1; i--)
            for(j=len2; j>=1; j--)
                if(a[i-1]==b[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 x,y;
        num=0;
        solve(a,len1);
        x=num;
        solve(b,len2);
        y=num-x;

        int ans=0;
        for(i=0; i<x; i++)
            for(j=0; j<y; j++)
                ans=Max(ans,dp1[pp[i][0]-1][pp[x+j][0]-1]+dp2[pp[i][1]+1][pp[x+j][1]+1]);
        printf("Case #%d: %d\n",++Count,ans+len3);
    }
    return 0;
}