HDU 4681 String dp

String

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=4681

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

题意

给你a,b,c串,你需要找到一个最长的d串

这个d串是ab串的子序列,然后c串是d串的子串

问你这个d串的长度是多少

题解:

数据范围1000,我们显然可以暴力枚举在a串的起始位置和在b串的起始位置

答案就是ansL + lenc + ansR

ansL就是ab串之前的最长公共子序列,ansR就是在匹配之后后面的最长公共子序列

lenc这个就是贪心匹配的最短位置在哪儿

这些东西都可以n^2的复杂度直接预处理

然后暴力去莽一波就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int dp1[maxn][maxn],dp2[maxn][maxn],l1[maxn],l2[maxn],len1,len2,len3;
char s1[maxn],s2[maxn],s3[maxn];

inline void update( int & x , int v ) { x = max( x , v ) ; }

void pre()
{
    for(int i=1;i<=len1;i++)
    {
        int l=1;
        for(int j=i;j<=len1;j++)
        {
            if(s1[j]==s3[l])l++;
            if(l>len3)
            {
                l1[i]=j;
                break;
            }
        }
    }
    for(int i=1;i<=len2;i++)
    {
        int l=1;
        for(int j=i;j<=len2;j++)
        {
            if(s2[j]==s3[l])l++;
            if(l>len3)
            {
                l2[i]=j;
                break;
            }
        }
    }
    for(int i=0 ;i< len1;i++)
    {
        for(int j=0 ;j< len2;j++)
        {
            if(s1[i + 1] == s2[j + 1] ) update( dp1[i+1][j+ 1] , dp1[i][j] + 1 );
            update(dp1[i + 1][j] , dp1[i][j] );
            update(dp1[i][j + 1] , dp1[i][j] );
        }
    }
    reverse(s1+1,s1+1+len1);
    reverse(s2+1,s2+1+len2);

    for(int i=0 ;i< len1;i++)
    {
        for(int j=0 ;j< len2;j++)
        {
            if(s1[i + 1] == s2[j + 1] ) update( dp2[i+1][j+ 1] , dp2[i][j] + 1 );
            update(dp2[i + 1][j] , dp2[i][j] );
            update(dp2[i][j + 1] , dp2[i][j] );
        }
    }
}
void solve(int cas)
{
    int ans = 0;
    for(int i=1;i<=len1;i++)
    {
        for(int j=1;j<=len2;j++)
        {
            if(l1[i]==-1||l2[j]==-1)continue;
            ans = max(dp1[i-1][j-1]+dp2[len1-l1[i]][len2-l2[j]]+len3,ans);
        }
    }
    printf("Case #%d: %d\n",cas,ans);
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        memset(l1,-1,sizeof(l1));
        memset(l2,-1,sizeof(l2));
        scanf("%s",s1+1);
        scanf("%s",s2+1);
        scanf("%s",s3+1);
        len1=strlen(s1+1),len2=strlen(s2+1),len3=strlen(s3+1);
        pre();
        solve(i);
    }
}

转载于:https://www.cnblogs.com/qscqesze/p/5493706.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值