zoukankan      html  css  js  c++  java
  • BZOJ3864 Hero meet devil dp套dp

    还是来存个dp套dp模板吧

    题目传送门

    题意是给你一个由ATGC组成的字符串,长度n<=15,求长度为m(<=1000)的字符串里有多少个满足与原串的最长公共子序列长度为i,i取0到n所有值

    考虑暴力,枚举所有长为m的字符串,dp求LCS

    不说了时间复杂度绝对爆炸

    来考虑递推式 :dp[i][j]=max(max(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]+[a[i]==b[j]](相等为1不等为0))

    那么,所有的dp[i]中,相邻的j差最多为1

    那么,我们可以把它压成状态,dp[i][sta]表示a在第i位,b的状态为sta时的方案数

    至于怎么转移这个问题,肯定不能每次枚举对吧

    那么就只好预处理出来了,用nxt[sta][j]表示状态为sta,下一步为k时转移到的状态

    最后统计状态sta中有多少个1,因为我们存的是差分结果,所以累加起来就是最后一位时的最长公共子序列长度(可以回忆最初的递推式,最初时的dp[n][m]就是LCS长度,对吧)(__builtin_popcount(i)是输出i转成2进制由多少个1),枚举一遍状态,统计入对应答案,然后就可以输出了

    代码一如既往地难看

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<vector>
    #include<iostream>
    #define ll int
    #define re register
    #define inf 0x3f3f3f3f
    #define inl inline
    #define sqr(x) (x*x)
    //#define eps 1e-8
    #define debug printf("debug
    ");
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#pragma GCC optimize (2)
    //#pragma G++ optimize (2)
    using namespace std;
    const ll mod=1e9+7;
    const ll MSTA=1<<15;
    const ll MAXN=20;
    inl ll read() {
        re ll x = 0; re int f = 1;
        char ch = getchar();
        while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
        while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x * f;
    }
    inl char readc() {
        char ch=getchar();
        while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
        return ch;
    }
    inl void write(re ll x){
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    inl void writeln(re ll x){
        if(x<0) {x=-x;putchar('-');}
        write(x); puts("");
    }
    inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
    inl void FR() {
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    }
    inl void FC() {
        fclose(stdin);
        fclose(stdout);
    }
    char ss[MAXN],dna[10]={'A','T','G','C'};
    ll m,n,nxt[MSTA][10],dp[5][MSTA],ans[MAXN];
    void init() {
        ll f[MAXN],g[MAXN];
        for(re ll i=0;i<(1<<n);i++) {
            memset(f,0,sizeof(f));
            memset(g,0,sizeof(g));
            for(re ll j=1;j<=n;j++) f[j]=f[j-1]+((i>>(j-1))&1);
            for(re ll k=0;k<4;k++) {
                for(re ll j=1;j<=n;j++) {
                    g[j]=max(g[j-1],f[j]);
                    if(dna[k]==ss[j]) g[j]=max(g[j],f[j-1]+1);
                }
                nxt[i][k]=0;
                for(re ll j=0;j<n;j++) {
                    if(g[j+1]-g[j]) {
                        nxt[i][k]|=(1<<j);
                    }
                }
            }
        }
    }
    int main() {
    //  FR(); 
        re ll T=read();
        while(T--) {
            scanf("%s",ss+1);
            n=strlen(ss+1);
            m=read();init();
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            bool flag=0;
            for(re ll i=1;i<=m;i++) {
                flag^=1;
                memset(dp[flag],0,sizeof(dp[flag]));
                for(re ll j=0;j<(1<<n);j++) {
                    for(re ll k=0;k<4;k++) {
                        dp[flag][nxt[j][k]]=(dp[flag][nxt[j][k]]+dp[flag^1][j])%mod;
                    }
                }
            }
            memset(ans,0,sizeof(ans));
            for(re ll i=0;i<(1<<n);i++) {
                ans[__builtin_popcount(i)]=(ans[__builtin_popcount(i)]+dp[m&1][i])%mod;
            }
            for(re ll i=0;i<=n;i++) writeln(ans[i]);
        }
    //  FC();
        return 0;
    }
  • 相关阅读:
    Greenplum使用简明手册
    VMware虚拟机下实现Linux与window文件夹共享
    SSH实现在WIN7系统下访问虚拟机中的Linux系统
    转_Greenplum 数据库安装部署(生产环境)
    政府大数据平台定位(转)
    国内外政府大数据六大典型应用
    从数据仓库到大数据,数据平台这25年是怎样进化的?
    转_【大话IT】你离大数据架构师有多远?
    js时间格式化和相互转换
    矢量图(字体图标)
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9381467.html
Copyright © 2011-2022 走看看