hdu 4681 String (dp预处理+枚举)

String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1250    Accepted Submission(s): 455


Problem Description
Given 3 strings A, B, C, find the longest string D which satisfy the following rules:
a) D is the subsequence of A
b) D is the subsequence of B
c) C is the substring of D
Substring here means a consecutive subsequnce.
You need to output the length of D.
 

Input
The first line of the input contains an integer T(T = 20) which means the number of test cases.
For each test case, the first line only contains string A, the second line only contains string B, and the third only contains string C.
The length of each string will not exceed 1000, and string C should always be the subsequence of string A and string B.
All the letters in each string are in lowercase.
 

Output
For each test case, output Case #a: b. Here a means the number of case, and b means the length of D.
 

Sample Input
  
  
2 aaaaa aaaa aa abcdef acebdf cf
 

Sample Output
  
  
Case #1: 4 Case #2: 3
Hint
For test one, D is "aaaa", and for test two, D is "acf".
 

Source


题意:
给定A、B、C三个串。求一个最长的串D。使得D是A,B串的公共子串(不要求连续),且使C为D的连续子串。

解题突破口:c串连续

思路:
满足条件的D串的形式为 x+c+z ;x为c前面的A、B最大连续子串,y为c后面的A、B最大连续子串,那么先预处理dp1[i][j] - A的i位置前面、B的j位置前面最长子序列,dp2[i][j] - A的i位置后面、B的j位置后面最长子序列,然后枚举c的首字母在A、B中的位置,预处理好c在此位置时分别延续到A、B最后面的位置,那么就可以O(1)更新ans了。

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 100005
#define mod 1000000007
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int n,m,ans;
int len1,len2,len3;
char a[maxn],b[maxn],c[maxn];
int dp1[maxn][maxn],dp2[maxn][maxn];
int last1[maxn],last2[maxn];
vector<int>v1,v2;

void presolve()
{
    int i,j,t;
    len1=strlen(a+1);
    len2=strlen(b+1);
    len3=strlen(c+1);
    memset(last1,0,sizeof(last1));
    memset(last2,0,sizeof(last2));
    memset(dp1,0,sizeof(dp1));
    memset(dp2,0,sizeof(dp2));
    v1.clear();
    for(i=1; i<=len1; i++)
    {
        if(a[i]==c[1])
        {
            v1.push_back(i);
            t=2;
            if(len3==1)
            {
                last1[i]=i;
                continue ;
            }
            for(j=i+1; j<=len1; j++)
            {
                if(a[j]==c[t])
                {
                    t++;
                    if(t>len3)
                    {
                        last1[i]=j;
                        break ;
                    }
                }
            }
        }
    }
    v2.clear();
    for(i=1; i<=len2; i++)
    {
        if(b[i]==c[1])
        {
            v2.push_back(i);
            t=2;
            if(len3==1)
            {
                last2[i]=i;
                continue ;
            }
            for(j=i+1; j<=len2; j++)
            {
                if(b[j]==c[t])
                {
                    t++;
                    if(t>len3)
                    {
                        last2[i]=j;
                        break ;
                    }
                }
            }
        }
    }
    for(i=1; i<=len1; i++)
    {
        for(j=1; j<=len2; j++)
        {
            if(a[i]==b[j]) dp1[i][j]=max(dp1[i][j],dp1[i-1][j-1]+1);
            else dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1]);
        }
    }
    for(i=len1; i>=1; i--)
    {
        for(j=len2; j>=1; j--)
        {
            if(a[i]==b[j]) dp2[i][j]=max(dp2[i][j],dp2[i+1][j+1]+1);
            else dp2[i][j]=max(dp2[i][j+1],dp2[i+1][j]);
        }
    }
}
void solve()
{
    int i,j,t,u,v;
    ans=0;
    for(i=0; i<v1.size(); i++)
    {
        for(j=0; j<v2.size(); j++)
        {
            u=v1[i];
            v=v2[j];
            if(last1[u]&&last2[v])
            {
                ans=max(ans,dp1[u-1][v-1]+dp2[last1[u]+1][last2[v]+1]+len3);
            }
        }
    }
}
int main()
{
    int i,j,t,test=0;
    scanf("%d",&t);
    for(i=1; i<=t; i++)
    {
        scanf("%s%s%s",a+1,b+1,c+1);
        presolve();
        solve();
        printf("Case #%d: %d\n",++test,ans);
    }
    return 0;
}
/*
2
acdbb
acdb
acd
cxxyxxjz
xyz
xz
*/






 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值