• BZOJ2764 [JLOI2011]基因补全


    Description

    在 生物课中我们学过,碱基组成了DNA(脱氧核糖核酸),他们分别可以用大写字母A,C,T,G表示,其中A总与T配对,C总与G配对。两个碱基序列能相互 匹配,当且仅当它们等长,并且任意相同位置的碱基都是能相互配对的。例如ACGTC能且仅能与TGCAG配对。一个相对短的碱基序列能通过往该序列中任意 位置补足碱基来与一个相对长的碱基序列配对。补全碱基的位置、数量不同,都将视为不同的补全方案。现在有两串碱基序列S和T,分别有n和m个碱基 (n>=m),问一共有多少种补全方案。
     

    Input

    数据包括三行。
    第一行有两个整数n,m,表示碱基序列的长度。
    第二行包含n个字符,表示碱基序列S。
    第三行包含m个字符,表示碱基序列T。
    两个碱基序列的字符种类只有A,C,G,T这4个大写字母。
     

    Output

     
    答案只包含一行,表示补全方案的个数。

    Sample Input

    10 3
    CTAGTAGAAG
    TCC

    Sample Output

    4

    HINT

    样例解释:

     

    TCC4种补全方案(括号中字符为补全的碱基)

     

    (GA)TC(AT)C(TTC)

     

    (GA)TC(ATCTT)C

     

    (GA)T(CAT)C(TT)C

     

    (GATCA)TC(TT)C

     

     

     

    数据范围:

     

    30%数据n<=1000,m<=2

     

    50%数据n<=1000,m<=4

     

    100%数据n<=2000,m<=n

     

     

    正解:DP+高精度

    解题报告:

      好久没写题了,感觉只要不是考试就写不动题了。。。

      这道题其实挺水的,就是一个编辑距离。考虑f[i][j]表示长串匹配到i,短串匹配到j的方案数,显然对于长串而言,我们需要在短串的对应位置补一些新的数字才行。所以f[i][j]=f[i-1][j]表示i这一位上与之相对应的短串上填一个新的数字,并且如果a[i]与b[j]能匹配,那么f[i][j]+=f[i-1][j-1];表示各匹配一位。

      因为答案很大,所以要写高精度。还要滚动数组。

     

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 2011;
    21 const int MOD = 100000000;
    22 int n,m;
    23 int match[5],a[MAXN],b[MAXN];
    24 //int f[MAXN][MAXN][10];//f[i][j]表示长串匹配到i,短串匹配到j的方案数,滚动数组
    25 //int cnt[MAXN][MAXN];
    26 int cnt[MAXN];
    27 int f[MAXN][50];
    28 
    29 inline int getint()
    30 {
    31        int w=0,q=0;
    32        char c=getchar();
    33        while((c<'0' || c>'9') && c!='-') c=getchar();
    34        if (c=='-')  q=1, c=getchar();
    35        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    36        return q ? -w : w;
    37 }
    38 /*
    39 inline void add(int x,int y,int i,int j){
    40     int now=1;
    41     if(cnt[x][y]<cnt[i][j]) cnt[x][y]=cnt[i][j];
    42     while(now<=cnt[x][y]) {
    43     f[x][y][now]+=f[i][j][now]; now++;
    44     }
    45     for(int i=1;i<=cnt[x][y];i++) 
    46     if(f[x][y][i]>=MOD) 
    47         f[x][y][i+1]+=f[x][y][i]/MOD,f[x][y][i]%=MOD;
    48     while(f[x][y][cnt[x][y]+1]) cnt[x][y]++;
    49 }*/
    50 
    51 inline void work(){
    52     n=getint(); m=getint(); char c;
    53     match[1]=3; match[2]=4; match[3]=1; match[4]=2;
    54     for(int i=1;i<=n;i++) {
    55     c=getchar();
    56     while(c<'A' || c>'T')  c=getchar();
    57     if(c=='A') a[i]=1; else if(c=='C') a[i]=2; else if(c=='T') a[i]=3; else a[i]=4;
    58     }
    59     for(int i=1;i<=m;i++) {
    60     c=getchar();
    61     while(c<'A' || c>'T') c=getchar();
    62     if(c=='A') b[i]=1; else if(c=='C') b[i]=2; else if(c=='T') b[i]=3; else b[i]=4;
    63     }
    64 
    65     f[0][1]=1; cnt[0]=1;
    66     for(int i=0;i<=m;i++) cnt[i]=1;
    67     for(int i=1;i<=n;i++)
    68     for(int j=m;j>=1;j--) {
    69         if(match[a[i]]!=b[j]) continue;
    70         if(cnt[j]<cnt[j-1]) cnt[j]=cnt[j-1];
    71         for(int l=1;l<=cnt[j];l++) {
    72         f[j][l]+=f[j-1][l];
    73         if(f[j][l]>=MOD) f[j][l+1]+=f[j][l]/MOD,f[j][l]%=MOD;
    74         }
    75         while(f[j][cnt[j]+1]) cnt[j]++;
    76     }
    77     printf("%d",f[m][cnt[m]]);
    78     for(int i=cnt[m]-1;i>=1;i--) printf("%08d",f[m][i]);
    79     /*
    80     for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) cnt[i][j]=1;
    81     for(int i=0;i<=n;i++) f[i][0][1]=1;
    82     for(int i=1;i<=n;i++)
    83     for(int j=m;j>=1;j--) {
    84         if(cnt[i][j]<cnt[i-1][j])cnt[i][j]=cnt[i-1][j];
    85         for(int l=1;l<=cnt[i-1][j];l++) f[i][j][l]=f[i-1][j][l]; //一位新添加一个数
    86         if(match[a[i]]==b[j]){
    87         add(i,j,i-1,j-1);//由上一位转移过来 
    88         }
    89     }
    90     printf("%d",f[n][m][cnt[n][m]]);
    91     for(int i=cnt[n][m]-1;i>=1;i--) printf("%08d",f[n][m][i]);*/
    92 }
    93 
    94 int main()
    95 {
    96   work();
    97   return 0;
    98 }
  • 相关阅读:
    继承Runnable 实现Synchronized 同步锁
    SSM框架整合(IntelliJ IDEA + maven + Spring + SpringMVC + MyBatis)
    Nginx采用yum安装-Carr
    SpringBoot idea maven打包war及运行war包
    根据现有PDF模板填充信息(SpringBoot)
    java后台简单从腾讯云下载文件通知前端以附件的形式保存
    java后台简单从阿里云上传下载文件并通知前端以附件的形式保存
    Security-OAuth2.0 密码模式之客户端实现
    Security-OAuth2.0 密码模式之服务端实现
    Redis-Java 交互的应用
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5789230.html
Copyright © 2020-2023  润新知