DP套DP HDOJ 4899 Hero meet devil(国王的子民的DNA)

 

题目链接

题意:

  给n长度的S串,对于0<=i<=|S|,有多少个长度为m的T串,使得LCS(S,T) = i。

思路:

  理解的不是很透彻,先占个坑。

#include <bits/stdc++.h>

const int S = (1 << 15) + 5;
const int MOD = 1e9 + 7;

char color[] = "ATGC";
char s[20];
int pre[20], lcs[20];
int dp[2][S], add[S][4];
int ans[20];
int n, m;

void add_mod(int &a, int b) {
    a += b;
    if (a >= MOD) {
        a -= MOD;
    }
}

int bit_count(int x) {
    return x ? bit_count (x >> 1) + (x & 1) : x;
}

void init() {
    n = strlen (s + 1);
    for (int state=0; state<(1<<n); ++state) {  //状压枚举S与T公共点的组合
        pre[0] = 0;
        for (int i=1; i<=n; ++i) {
            pre[i] = pre[i-1] + ((state>>(i-1)) & 1);  //S匹配到前i个时LCS的长度
        }
        for (int k=0; k<4; ++k) {  //T的某一个位置是color[k],新的LCS的长度和公共点位置
            for (int i=1; i<=n; ++i) {
                if (s[i] == color[k]) {
                    lcs[i] = pre[i-1] + 1;
                } else {
                    lcs[i] = std::max (lcs[i-1], pre[i]);
                }
            }

            int &tmp = add[state][k] = 0;  //对于state状态,加一个颜色k后新的state
            for (int i=1; i<=n; ++i) {
                tmp |= ((lcs[i]!=lcs[i-1]) << (i-1));
            }
        }
    }
}

void solve() {
    int now = 0;
    memset (dp[now], 0, sizeof (dp[now]));
    dp[now][0] = 1;
    for (int i=1; i<=m; ++i) {
        now ^= 1;
        memset (dp[now], 0, sizeof (dp[now]));
        for (int state=0; state<(1<<n); ++state) {
            for (int k=0; k<4; ++k) {
                add_mod (dp[now][add[state][k]], dp[now^1][state]);
            }
        }
    }
    memset (ans, 0, sizeof (ans));
    for (int state=0; state<(1<<n); ++state) {
        add_mod (ans[bit_count (state)], dp[now][state]);
    }
    for (int i=0; i<=n; ++i) {
        printf ("%d\n", ans[i]);
    }
}

int main() {
    int T;
    scanf ("%d", &T);
    while (T--) {
        scanf ("%s", s + 1);
        scanf ("%d", &m);
        init ();
        
        solve ();
    }
    return 0;
}

  

 

posted @ 2016-07-18 10:49  Running_Time  阅读(304)  评论(0编辑  收藏  举报