BZOJ 3864 Hero meet devil DP套DP

50 篇文章 1 订阅
12 篇文章 1 订阅
该博客主要介绍了如何利用动态规划和状压DP解决BZOJ 3864题目的基因序列LCS(最长公共子序列)问题。博主探讨了如何定义状态和转移,并且提到了状态数不超过2n,可以使用二进制数存储相邻状态的差值,最后给出了O(4*n*2^n + 4*m*2^n)的时间复杂度预处理和DP方法。
摘要由CSDN通过智能技术生成

题目大意:给定一个长度为 n(n15) 的基因序列 S ,求对于每个i(0in)有多少长度为 m(m1000) 的基因串 T 满足S T LCS i

考虑LCS怎么求
fi,j 表示 T 的前i位和 S 的前j位的 LCS
我们发现每一行之和上一行的状态有关

那么在这个问题中,我们令 fi,j 表示 T 的前i位与 S LCS状态的第 i 行为j的状态数
由于每一行相邻两数最多差 1 ,因此状态数不会超过2n,用一个二进制数存储相邻两项的差值即可
预处理所有转移后直接DP,时间复杂度 O(4n2n+4m2n)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MOD 1000000007
using namespace std;
const char letters[]={'A','C','G','T'};
int n,m;
char s[20];
int trans[1<<15][4],cnt[1<<15],f[2][1<<15];
void Pretreatment()
{
    int i,j,k;
    for(i=0;i<1<<n;i++)
    {
        static int f[20],g[20];
        for(j=1;j<=n;j++)
            f[j]=f[j-1]+(i&(1<<j-1)?1:0);
        cnt[i]=f[n];
        for(k=0;k<4;k++)
        {
            for(j=1;j<=n;j++)
            {
                g[j]=max(g[j-1],f[j]);
                if(letters[k]==s[j])
                    g[j]=max(g[j],f[j-1]+1);
            }
            trans[i][k]=0;
            for(j=1;j<=n;j++)
                if(g[j]-g[j-1])
                    trans[i][k]|=1<<j-1;
        }

    }
}
int main()
{
    int T,i,j,k;
    for(cin>>T;T;T--)
    {
        scanf("%s%d",s+1,&m);
        n=strlen(s+1);
        Pretreatment();
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(i=1;i<=m;i++)
        {
            memset(f[i&1],0,sizeof(f[0][0])<<15);
            for(j=0;j<1<<n;j++)
                for(k=0;k<4;k++)
                    (f[i&1][trans[j][k]]+=f[~i&1][j])%=MOD;
        }
        static int ans[20];
        memset(ans,0,sizeof ans);
        for(i=0;i<1<<n;i++)
            (ans[cnt[i]]+=f[m&1][i])%=MOD;
        for(i=0;i<=n;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值