HDU 4681 String 胡搞

设串C的第一个字母在串A中出现的位置是stA, 串C的最后一个字母在串A中出现的位置是edA。

设串C的第一个字母在串B中出现的位置是stB, 串C的最后一个字母在串B中出现的位置是edB。

求出每一对合法的(stA, edA),(stB, edB)

对每一组( stA[i], edA[i] ) 和 ( stB[j], ed[j] ), 求串A[0,stA[i]-1]和串B[0, stB[j]-1]的最长公共子序列长度L1, 求串A[edA[i]+1, lenA-1]和串B[stB[j]+1, lenB-1]的最长公共子序列长度L2, 答案为max( lenC+L1+L2 )……

现在看看自己赛场上写的代码觉得自己好脑残啊……虽然不紧张但是当时在TLE了N次之后已经觉得脑子是一团浆糊了,我从机子上下静下心仔细想想的时候才发现我根本没理解透薛薛的意思。下次觉得自己不好了的时候一定要果断换人,不然太耽误时间了orz……

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 1010

using namespace std;

int N;
int c1[maxn][maxn];
int c2[maxn][maxn];
int duiA[maxn][2];
int duiB[maxn][2];
int cntA, cntB;
char strA[maxn], strB[maxn], strC[maxn];
char ReA[maxn], ReB[maxn];
int lenA, lenB, lenC;

void Calc(char* a, char* b, int c[maxn][maxn])
{
    int i,j;
    int la=strlen(a);
    int lb=strlen(b);
    for(i=0; i<la; i++)
        c[i][0]=0;
    for(j=0; j<lb; j++)
        c[0][j]=0;
    for(i=1; i<=la; i++)
    {
        for(j=1; j<=lb; j++)
        {
            if(a[i-1]==b[j-1])
                c[i][j]=c[i-1][j-1]+1;
            else
            {
                if(c[i][j-1]>c[i-1][j])
                    c[i][j]=c[i][j-1];
                else
                    c[i][j]=c[i-1][j];
            }
        }
    }
    return;
}

int solved()
{
    int tmpans = 0;

    for ( int i = 0; i < cntA; ++i )
        for ( int j = 0; j < cntB; ++j )
        {
            int preA = duiA[i][0] - 1, preB = duiB[j][0] - 1;
            int sufA = lenA - duiA[i][1];
            int sufB = lenB - duiB[j][1];
            //printf("c1[%d][%d]=%d c2[%d][%d]=%d\n", preA, preB, c1[preA][preB], duiA[i][1], duiB[j][i], c2[sufA][sufB] );
            int tmp = 0;
            if ( preA > 0 && preB > 0 ) tmp += c1[preA][preB];
            if ( sufA > 0 && sufB > 0 ) tmp += c2[sufA][sufB];
            tmpans = max( tmpans, tmp );
        }

    return tmpans;
}

void preSolved()
{
    cntA = 0;
    cntB = 0;

    for ( int i = 0; i + lenC < lenA; ++i )
    {
        if ( strA[i] != strC[0] ) continue;
        int cur = i + 1, j;
        for ( j = 1; j < lenC && cur < lenA; )
        {
            if ( strA[cur] == strC[j] ) ++j;
            ++cur;
        }
        if ( j == lenC )
        {
            duiA[cntA][0] = i + 1;
            duiA[cntA][1] = cur;
            ++cntA;
        }
    }

    for ( int i = 0; i + lenC < lenB; ++i )
    {
        if ( strB[i] != strC[0] ) continue;
        int cur = i + 1, j;
        for ( j = 1; j < lenC && cur < lenB; )
        {
            if ( strB[cur] == strC[j] ) ++j;
            ++cur;
        }
        if ( j == lenC )
        {
            duiB[cntB][0] = i + 1;
            duiB[cntB][1] = cur;
            ++cntB;
        }
    }

    return;
}

int main()
{
    //freopen("s.txt", "w", stdout );
    int T, cas = 0;
    scanf( "%d", &T );
    while ( T-- )
    {
        scanf( "%s", strA );
        scanf( "%s", strB );
        scanf( "%s", strC );
        lenA = strlen( strA );
        lenB = strlen( strB );
        lenC = strlen( strC );
        if ( lenC == lenA || lenC == lenB )
        {
            printf( "Case #%d: %d\n", ++cas, lenC );
            continue;
        }
        Calc( strA, strB, c1 );
        for ( int i = lenA - 1; i >= 0; --i ) ReA[lenA-1-i] = strA[i];
        for ( int i = lenB - 1; i >= 0; --i ) ReB[lenB-1-i] = strB[i];
        ReA[lenA] = '\0', ReB[lenB] = '\0';
        Calc( ReA, ReB, c2 );

        preSolved();
        int ans = solved() + lenC;
        printf( "Case #%d: %d\n", ++cas, ans );
    }
    return 0;
}

 

posted @ 2013-08-15 23:04  冰鸮  阅读(317)  评论(0编辑  收藏  举报