hdu4681 String

本文介绍了一种解决特定字符串匹配问题的方法,即寻找两个字符串中最长的共同子序列,并确保第三个给定字符串作为子串存在其中。通过预处理和枚举技术实现了解决方案。

String

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


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
 

Recommend
zhuyuanchen520
 


简单题,预处理一下从前和从后面的最长公共子序列,然后暴力找c在a和b里的出现位置,枚举一下就行了。

。。。懒得用函数,所以代码有点难看……

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

char a[1005];
char b[1005];
char c[1005];
int frontdp[1005][1005];
int taildp[1005][1005];

typedef struct
{
    int begin,end;
}Interval;

Interval one[1005];
Interval two[1005];

int main()
{
    int i,j,na,nb,nc,T,cnt=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s%s",a,b,c);
        na=strlen(a);
        nb=strlen(b);
        nc=strlen(c);
        memset(frontdp,0,sizeof(frontdp));
        memset(taildp,0,sizeof(taildp));
        for (i=0;i<na;i++)
        {
            for (j=0;j<nb;j++)
            {
                if (i==0 && j==0) frontdp[i][j]=(a[i]==b[j]);
                else if (i==0) frontdp[i][j]=max(frontdp[i][j-1],(int)(a[i]==b[j]));
                else if (j==0) frontdp[i][j]=max(frontdp[i-1][j],(int)(a[i]==b[j]));
                else if (a[i]==b[j]) frontdp[i][j]=frontdp[i-1][j-1]+1;
                else frontdp[i][j]=max(frontdp[i][j-1],frontdp[i-1][j]);
            }
        }
        for (i=na-1;i>=0;i--)
        {
            for (j=nb-1;j>=0;j--)
            {
                if (i==na-1 && j==nb-1) taildp[i][j]=(a[i]==b[j]);
                else if (i==na-1) taildp[i][j]=max(taildp[i][j+1],(int)(a[i]==b[j]));
                else if (j==nb-1) taildp[i][j]=max(taildp[i+1][j],(int)(a[i]==b[j]));
                else if (a[i]==b[j]) taildp[i][j]=taildp[i+1][j+1]+1;
                else taildp[i][j]=max(taildp[i][j+1],taildp[i+1][j]);
          //      printf("%d ",taildp[i][j]);
            }
         //   printf("\n");
        }
        int upa,upb,up;
        upa=0;upb=0;
        for (i=0;i<na;i++)
        {
            up=0;
            if (a[i]!=c[0]) continue;
            for (j=i;j<na;j++)
            {
                if (a[j]==c[up])
                {
                    up++;
                    if (up==nc) break;
                }
            }
            if (j<na)
            {
                Interval tmp;
                tmp.begin=i;
                tmp.end=j;
                one[upa++]=tmp;
            }
        }
        for (i=0;i<nb;i++)
        {
            up=0;
            if (b[i]!=c[0]) continue;
            for (j=i;j<nb;j++)
            {
                if (b[j]==c[up])
                {
                    up++;
                    if (up==nc) break;
                }
            }
            if (j<nb)
            {
                Interval tmp;
                tmp.begin=i;
                tmp.end=j;
                two[upb++]=tmp;
            }
        }
        int ans=0;
        for (i=0;i<upa;i++)
        {
            for (j=0;j<upb;j++)
            {
                int f,t;
                if (one[i].begin==0 || two[j].begin==0) f=0;
                else f=frontdp[one[i].begin-1][two[j].begin-1];
                if (one[i].end==na-1 || two[j].end==nb-1) t=0;
                else t=taildp[one[i].end+1][two[j].end+1];
                ans=max(ans,f+t+nc);
            //    printf("%d %d %d %d %d %d %d\n",one[i].begin,one[i].end,two[j].begin,two[j].end,f,t,t+f+nc);
            }
        }
        printf("Case #%d: %d\n",cnt++,ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值