BZOJ 3864 Hero meet devil DP套DP

题目大意:给定一个长度为n(n15)<script type="math/tex" id="MathJax-Element-1696">n(n\leq 15)</script>的基因序列S<script type="math/tex" id="MathJax-Element-1697">S</script>,求对于每一个i(0in)<script type="math/tex" id="MathJax-Element-1698">i(0\leq i\leq n)</script>有多少长度为m(m1000)<script type="math/tex" id="MathJax-Element-1699">m(m\leq1000)</script>的基因串T<script type="math/tex" id="MathJax-Element-1700">T</script>满足S<script type="math/tex" id="MathJax-Element-1701">S</script>与T<script type="math/tex" id="MathJax-Element-1702">T</script>的LCS<script type="math/tex" id="MathJax-Element-1703">LCS</script>为i<script type="math/tex" id="MathJax-Element-1704">i</script>

考虑LCS<script type="math/tex" id="MathJax-Element-1705">LCS</script>怎么求
fi,j<script type="math/tex" id="MathJax-Element-1706">f_{i,j}</script>表示T<script type="math/tex" id="MathJax-Element-1707">T</script>的前i<script type="math/tex" id="MathJax-Element-1708">i</script>位和S<script type="math/tex" id="MathJax-Element-1709">S</script>的前j<script type="math/tex" id="MathJax-Element-1710">j</script>位的LCS<script type="math/tex" id="MathJax-Element-1711">LCS</script>
我们发现每一行之和上一行的状态有关

那么在这个问题中,我们令fi,j<script type="math/tex" id="MathJax-Element-1712">f_{i,j}</script>表示T<script type="math/tex" id="MathJax-Element-1713">T</script>的前i<script type="math/tex" id="MathJax-Element-1714">i</script>位与S<script type="math/tex" id="MathJax-Element-1715">S</script>的LCS<script type="math/tex" id="MathJax-Element-1716">LCS</script>状态的第i<script type="math/tex" id="MathJax-Element-1717">i</script>行为j<script type="math/tex" id="MathJax-Element-1718">j</script>的状态数
因为每一行相邻两数最多差1<script type="math/tex" id="MathJax-Element-1719">1</script>。因此状态数不会超过2n<script type="math/tex" id="MathJax-Element-1720">2^n</script>,用一个二进制数存储相邻两项的差值就可以
预处理全部转移后直接DP,时间复杂度O(4n2n+4m2n)<script type="math/tex" id="MathJax-Element-1721">O(4*n*2^n+4*m*2^n)</script>

#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;
}
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('
    ').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('
  • ').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
---

延伸阅读

想要更系统地学习?推荐以下课程:

  1. 数据结构与算法之美从零开始学习数据结构与算法,轻松应对编程面试

部署资源

posted @ 2017-08-14 14:17  clnchanpin  阅读(578)  评论(0)    收藏  举报