• uva 10723 Cyborg Genes


    题意:给出两个串a,b,去构建另一个串,新构建出来的串要满足两个性质。一,在这个新的串中选出一个子集是a串,另外选出一个子串是b,满足这个条件后,要求这个串的长度最短。也可以这样说,ab两个串合并为一个新串,不改变a,b串本身的相对位置,但是要求新串长度最短。输出这样的新串的个数

    所以基本上可以想到,是和LCS有关的,再细想,那就是算出LCS的长度,然后ab两串长度之和减去LCS的长度,相当于ab两串合并为一串,消去他们的共有元素,那么新串中还是包含了a,b串的所有元素还是可以选出一部分子集来得到a或b串的。

    但问题时,怎么构建,另外有多少种构建方法,实际上构建的方案数就是最后新串的个数

    我们可以模仿LCS的构建方法来思考这个问题    c[i][j]表示a串前i个元素和b串前j个元素所能得到的方案数。l[i][j]表示LCS的长度

    若a[i]=b[j],那么c[i][j]=c[i-1][j-1],即a串前i-1个元素和b串前j-1个元素得到的组合串的末尾加上一个相同的元素a[i],那么得到的新的组合串的个数还是和之前的组合串的个数一样

    若a[i]!=b[j],  l[i][j]=max { l[i-1][j] , l[i][j-1]}

    若l[i-1][j]>l[i][j-1],那说明从l[i-1][j]这种状态开始构建才能得到最终的LCS同时最终的组合串才不能漏掉共有的元素,所以c[i][i]=c[i-1][j],即在a串i-1个元素和b串j个元素组成的组合串的后面加上a[i],那么得到的新的组合串的个数和之前的组合串的个数是相同的

    若l[i][j-1]>l[i-1][j],道理和上面是一样的,所以c[i][j]=c[i][j-1],相当于在之前的组合串后面加上元素b[j],得到新的组合串的个数不变

    若l[i][j-1]=l[i-1][j],说明从两种状态都是能得到最终的LCS并且最终的组合串不会漏掉任何相同的公共元素,所以c[i][j]=c[i-1][j]+c[i][j-1] , 即用a串的i-1个元素和b串的j个元素组成的组合串的最后加上a[i]得到新的组合串和之前的组合串个数相同,另外用a串的i个元素和b串的的j-1个元素组成的组合串的最后加上b[j]得到新的组合串和之前的组合串个数相同,那么就是两者之和

    另外读取a,b串的时候要用gets,就这样WA了两次

    另外c[][]数组同long long 

    #include <stdio.h>
    #include <string.h>
    #define MAX 40
    char a[MAX],b[MAX];
    int l[MAX][MAX];
    long long c[MAX][MAX];
    int lena ,lenb;
    
    int main()
    {
        int T,t,i,j;
        scanf("%d",&T); getchar();
        for(t=1; t<=T; t++)
        {
            gets(a+1);
            gets(b+1);
            //scanf("%s%s",a+1,b+1);
            lena=strlen(a+1);
            lenb=strlen(b+1);
    
            memset(l,0,sizeof(l));
            memset(c,0,sizeof(c));
            for(i=0; i<=lena; i++)
                c[i][0]=1;
            for(i=0; i<=lenb;  i++)
                c[0][i]=1;
    
            for(i=1; i<=lena; i++)
                for(j=1; j<=lenb; j++)
                {
                    if(a[i]==b[j])
                    {
                        l[i][j]=l[i-1][j-1]+1;
                        c[i][j]=c[i-1][j-1];
                    }
                    else
                    {
                        if(l[i-1][j]>l[i][j-1])
                        {
                            l[i][j]=l[i-1][j];
                            c[i][j]=c[i-1][j];
                        }
                        else if(l[i][j-1]>l[i-1][j])
                        {
                            l[i][j]=l[i][j-1];
                            c[i][j]=c[i][j-1];
                        }
                        else
                        {
                            l[i][j]=l[i-1][j];
                            c[i][j]=c[i-1][j]+c[i][j-1];
                        }
                    }
                }
    
            printf("Case #%d: %d %lld\n",t,lena+lenb-l[lena][lenb] , c[lena][lenb]);
        }
        return 0;
    }
  • 相关阅读:
    Entity Framework 教程
    C# yield
    表达式树系列文章汇总
    C#中静态与非静态方法比较
    谈谈对Spring IOC的理解
    工厂方法模式与IoC/DI
    通过配置的方式Autofac 《第三篇》
    Autofac 组件、服务、自动装配 《第二篇》
    Autofac 解释第一个例子 《第一篇》
    SQL Server索引调优系列
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2709781.html
Copyright © 2020-2023  润新知