zoukankan      html  css  js  c++  java
  • bzoj3864: Hero meet devil

    http://www.lydsy.com/JudgeOnline/problem.php?id=3864

    题意:

    给你一个DNA序列,求有多少个长度为m的DNA序列和给定序列的LCS为0,1,2....

    求LCS方式:f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]*(s[i]==t[j]))

    固定了i,相邻的j的f[i][j]值最多相差1

    dp[i][j] 表示长度为i的DNA序列,将“f[ |S| ][j+1]是否比f[ |S| ][j] 大1” 这个状态压缩为j的方案数

    若我们知道 状态j加上一个字母k可以到状态nxt[j][k]

    那么dp[i+1][nxt[j][k]]+=dp[i][j]

    关键是如何求得nxt[j][k]

    再一次DP

    枚举所有的状态i

    令f[j] 表示加上字母k之前的LCS长度,g[j]表示加上字母k之后的LCS长度

    g[j]=max(g[j-1],f[j])

    如果加上的字母k和原序列第j个字母匹配 g[i]=max(g[j],f[j-1]+1)

    g求完后,项邻的两个g要么相等,要么相差1

    再把这个状态压缩起来即可

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int mod=1e9+7;
    
    int m;
    
    char ss[16];
    int L,S;
    int s[16];
    
    int ch[26];
    
    int f[16],g[16];
    int nxt[1<<15][4];
    
    int dp[2][1<<15];
    int ans[16];
    
    void pre()
    {
        int len; int c[16];
        for(int i=0;i<S;++i)
        {
            memset(f,0,sizeof(f));
            for(int j=1;j<=L;++j) f[j]=f[j-1]+(i>>j-1&1);
            for(int k=0;k<4;++k)
            {
                for(int j=1;j<=L;++j)
                {
                    g[j]=max(g[j-1],f[j]);
                    if(s[j]==k) g[j]=max(g[j],f[j-1]+1);
                }
                nxt[i][k]=0;
                for(int j=0;j<L;++j)
                    if(g[j+1]-g[j]) nxt[i][k]+=1<<j;
            }
        }
    }
    
    int count(int x)
    {
        int sum=0;
        while(x)
        {
            sum+=x&1;
            x>>=1;
        }
        return sum;
    }
    
    void DP()
    {
        memset(dp,0,sizeof(dp));
        int now=1,last=0;
        dp[0][0]=1;
        for(int i=1;i<=m;++i)
        {
            memset(dp[now],0,sizeof(dp[now]));
            for(int j=0;j<S;++j)
                for(int k=0;k<4;++k)
                {
                    dp[now][nxt[j][k]]+=dp[last][j];
                    dp[now][nxt[j][k]]-=dp[now][nxt[j][k]]>=mod ? mod : 0;
                }
            swap(now,last);
        }
        memset(ans,0,sizeof(ans));
        int t;
        for(int i=0;i<S;++i) 
        {
            t=count(i);
            ans[t]+=dp[last][i];
            ans[t]-=ans[t]>=mod ? mod : 0;
        }
        for(int i=0;i<=L;++i) printf("%d
    ",ans[i]);
    }
    
    int main()
    {
        ch['A'-'A']=0;
        ch['C'-'A']=1;
        ch['G'-'A']=2;
        ch['T'-'A']=3;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",ss+1);
            scanf("%d",&m);
            L=strlen(ss+1);
            S=1<<L;
            for(int i=1;i<=L;++i) s[i]=ch[ss[i]-'A'];
            pre();
            DP();
        }
        return 0;
    }
  • 相关阅读:
    黄金连分数
    第39级台阶
    四、绘图可视化之Seaborn
    三、绘图和可视化之matplotlib
    二、pandas入门
    python_111_动态导入模块
    爬虫_python3_抓取猫眼电影top100
    爬虫_python3_urllib
    python_112_网络编程 Socket编程
    python_111_异常处理
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8454799.html
Copyright © 2011-2022 走看看