复读子串 Repeated Subsequences [EOlymp – 3624]题解

复读子串 Repeated Subsequences [EOlymp – 3624]题解

最长公共子列问题。

这个题的时限特别长,是10秒钟,看来似乎是可以枚举串的所有分组并逐一计算LCS。

先写能够计算最长公共子序列的函数,然后对每种切分方式(遍历所有可切分的点),分别计算两串的最长公共子序列,记下最长的长度和序列,然后输出最长的那个序列即可。此题思路不难,关键在于如何输出最长公共子序列以及如何适当的存储中间数据。

#include <cstdio>
#include <cstring>
#include <algorithm>
using std::max;

int LCS(char* s1, char* s2,char *res)
{
    int i,j,M,N,k=0,upbd;
    M=strlen(s1);
    N=strlen(s2);
    int **dp;
    dp=new int* [M+2];
    for(i=0;i<M+2;i++)
        dp[i]=new int [N+2];
    for(i=0;i<N+2;i++)
        dp[0][i]=0;
    
    for(i=1;i<M+1;i++)
    {
        dp[i][0]=0;
        for(j=1;j<N+1;j++)
        {
            if(s1[i-1]==s2[j-1])
                dp[i][j]=dp[i-1][j-1]+1;
            else
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    k=dp[M][N];

    i=M;
    j=N;
    upbd=k;
    res[k]='\0';
    while(i>0 && j>0)
    {
        if(dp[i-1][j]==dp[i-1][j-1] && dp[i-1][j-1]==dp[i][j-1] )
        {
            if (dp[i][j]==dp[i-1][j-1]+1)
                res[--upbd]=s1[i-1];
            i--;
            j--;
        }
        else
        {
            if(dp[i-1][j]==dp[i][j])
                i--;
            else
                j--;
        }
    }
    for(i=0;i<M+2;i++)
        delete [] dp[i];
    delete [] dp;

    return k;
}

void solve(char *s)
{
    char *s1,*s2,*res,*target;
    int N=strlen(s),i,d,maxVal=-1;
    s1=new char [N+1];
    s2=new char [N+1];
    res=new char [N+1];
    target=new char [N+1];
    for(i=1;i<N;i++)
    {
        strcpy(s1,s);
        s1[i]=0;
        strcpy(s2,s+i);

        d=LCS(s1,s2,res);
        if(d>maxVal)
        {
            maxVal=d;
            strcpy(target,res);
        }
    }
    printf("%s\n",target);
    delete [] s1;
    delete [] s2;
    delete [] res;
    delete [] target;
}

#define MAXLENGTH 303
int main(void)
{
    char s[MAXLENGTH];
    while(scanf("%s",s)!=EOF)
    {
        if(strcmp("#END",s)==0)
            break;
        solve(s);

    }

    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注