HDU4681_String

这个题目是这样的。

给你三个字符串A,B,C,(C一定是A和B的一个公共子序列)。

现在要求你构造出一个串D,使得D同时为A和B的子序列,且C是D的一个连续子串。求D的最大可能长度。

很简单的一个DP题。

其实这个题目有三个预处理就可以搞定了。

1、f1[i][j]:A的前i个字符,B的前J个字符的最长公共子序列。

2、f2[i][j]:A的i个字符以后,B的第J个字符以后的字符的最长公共子序列。

3、A和B串以某个位置开始作为C的子序列时,最近的匹配距离(最近匹配完的那个地方)。

有了这三个预处理,剩下的只要直接暴力枚举A和B中匹配的开始位置即可。

#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 1015
using namespace std;

int f1[maxn][maxn],f2[maxn][maxn],pos1[maxn],pos2[maxn],L1,L2,L,ans,cas=0,t;
char s1[maxn],s2[maxn],s[maxn];

int main()
{
    scanf("%d",&t);
    while (t--)
    {
        memset(f1,0,sizeof f1);
        memset(f2,0,sizeof f2);
        memset(s,0,sizeof s);
        memset(pos1,0,sizeof pos1);
        memset(pos2,0,sizeof pos2);
        memset(s1,0,sizeof s1);
        memset(s2,0,sizeof s2);
        scanf("%s",s1+1);scanf("%s",s2+1);scanf("%s",s+1);
        L1=strlen(s1+1),L2=strlen(s2+1),L=strlen(s+1);
        for (int i=1; s1[i]; i++)
            for (int j=1; s2[j]; j++)
            {
                f1[i][j]=max(f1[i-1][j],f1[i][j-1]);
                if (s1[i]==s2[j])
                    f1[i][j]=max(f1[i][j],f1[i-1][j-1]+1);
            }
        f2[L1+1][L2]=f2[L1][L2+1]=f2[L1+1][L2+1]=0;
        for (int i=L1; i>0; i--)
            for (int j=L2; j>0; j--)
            {
                f2[i][j]=max(f2[i+1][j],f2[i][j+1]);
                if (s1[i]==s2[j])
                    f2[i][j]=max(f2[i][j],f2[i+1][j+1]+1);
            }
        for (int i=1; s1[i]; i++)
        {
            if (s1[i]!=s[1])
            {
                pos1[i]=0;
                continue;
            }
            int cur=1,j=i;
            for (; s1[j]; j++)
            {
                if (s1[j]==s[cur]) cur++;
                if (!s[cur]) break;
            }
            if (!s[cur]) pos1[i]=j;
                else pos1[i]=0;
        }
        for (int i=1; s2[i]; i++)
        {
            if (s2[i]!=s[1])
            {
                pos2[i]=0;
                continue;
            }
            int cur=1,j=i;
            for (;s2[j]; j++)
            {
                if (s2[j]==s[cur]) cur++;
                if (!s[cur]) break;
            }
            if (!s[cur]) pos2[i]=j;
                else pos2[i]=0;
        }
        ans=L;
        for (int i=1; s1[i]; i++)
        {
            if (pos1[i]==0) continue;
            for (int j=1; s2[j]; j++)
            {
                if (pos2[j]==0) continue;
                ans=max(ans,L+f1[i-1][j-1]+f2[pos1[i]+1][pos2[j]+1]);
            }
        }
        printf("Case #%d: %d
",++cas,ans);
    }
    return 0;
}
如有转载,请注明出处(http://www.cnblogs.com/lochan)
原文地址:https://www.cnblogs.com/lochan/p/3450195.html