HDU 4681 String (LCS+暴力枚举)

String

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


 

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

2013 Multi-University Training Contest 8

 

 

Recommend

zhuyuanchen520   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long

const int  maxn =1e3+5;
const int mod=1e9+7;
/*
题目大意:给定三个字符串,
要求求出符合条件的字符串的最大长度,
该字符串是前两个字符串的子串,
并且第三个字符串必须是该字符串的连续子串。

该算法支持平方复杂度。
首先求LCS,正序和逆序。
然后暴力枚举在两个字符串中第三个字符串出现的位置区间,
小贪心一下,检索到恰好出现的位置,这样保证答案最优。

中途的区间位置用结构体记录下即可,然后扫描结构体数组枚举答案。

*/

char a[maxn],b[maxn],c[maxn];
int dp1[maxn][maxn],dp2[maxn][maxn];

struct node { int x,y; };
node _a[maxn],_b[maxn];///a串的位置,b串中的位置
int ta,tb;

int main()
{
    int t;scanf( "%d" , &t ) ;getchar();
    for(int ca=1;ca<=t;ca++)
    {
        gets(a+1);
        gets(b+1);///getchar();
        gets(c+1);///
        int l1=strlen( a+1 ),l2=strlen( b+1 ),l3=strlen(c+1);

        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));

        dp1[1][1]=(a[1]==b[1]);
        for(int i=1;i<=l1;i++)
            for(int j=1;j<=l2;j++)
            {
                if(i==1 && j==1) continue;
                if(a[i]==b[j]) dp1[i][j]=dp1[i-1][j-1]+1;
                else  dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1]);
            }

        dp2[l1][l2]=(a[l1]==b[l2]);
        for(int i=l1;i>=1;i--)
            for(int j=l2;j>=1;j--)
            {
                if(i==l1 && j==l2) continue;
                if(a[i]==b[j]) dp2[i][j]=dp2[i+1][j+1]+1;
                else dp2[i][j]=max( dp2[i+1][j] , dp2[i][j+1] );
            }

        ///最长公共子序列的正序和逆序。
        ///找出C串在A,B串的位置。
        ///暴力预处理

        if(l3==0) { printf("%d\n",dp1[l1][l2]);continue; }

        ta=0,tb=0;
        for(int i=1;i<=l1;i++)
        {
            int nxt=1,pos=0;
            if(a[i]==c[1])
            {
                for(int j=i;j<=l1;j++)
                {
                    if(a[j] == c[nxt]) nxt++;
                    if(nxt==l3+1) {pos=j+1;break;}///第一次的位置截止
                }
            }
            if(pos)
            {
                _a[ta].x=i-1;
                _a[ta].y=pos;
                ta++;
            }
        }

        for(int i=1;i<=l2;i++)
        {
            int nxt=1,pos=0;
            if(b[i]==c[1])
            {
                for(int j=i;j<=l2;j++)
                {
                    if(b[j]==c[nxt]) nxt++;
                    if(nxt==l3+1) {pos=j+1;break;}///第一次的位置截止
                }
            }
            if(pos)
            {
                _b[tb].x=i-1;
                _b[tb].y=pos;
                tb++;
            }
        }

        int ans=0;
        for(int i=0;i<ta;i++)
        {
            for(int j=0;j<tb;j++)
            {
                int x1=_a[i].x,y1=_a[i].y;
                int x2=_b[j].x,y2=_b[j].y;
                ans=max(ans,dp1[x1][x2]+dp2[y1][y2]+l3);
            }
        }
        printf("Case #%d: %d\n",ca,ans);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值