BZOJ 3864 Hero Meets Devil

Solution

$f_{i, j} = \max \begin{cases} f_{i - 1, j} \\ f_{i, j - 1} \\ f_{i - 1, j - 1} + [s_i = t_j] \end{cases}$

$LCS(s, t) = f[|S|][|T|]$.

$ans[k] = \sum_{F} g[|T|][F] \times [F[|T|] = k]$

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 15, MOD = (int)1e9 + 7;
int t[N + 7];
int n, m;
int main()
{

#ifndef ONLINE_JUDGE

freopen("gene.in", "r", stdin);
freopen("gene.out", "w", stdout);

#endif

int T; scanf("%d\n", &T);
for (int cs = 0; cs < T; ++ cs)
{
static char str[N + 7]; scanf("%s", str + 1);
n = strlen(str + 1); scanf("%d\n", &m);
for (int i = 1; i <= n; ++ i)
if (str[i] == 'A') t[i] = 1;
else if (str[i] == 'T') t[i] = 2;
else if (str[i] == 'G') t[i] = 3;
else if (str[i] == 'C') t[i] = 4;
static int trans[(1 << N) + 7][7];
for (int j = 0; j < 1 << n; ++ j) for (int c = 1; c <= 4; ++ c)
{
static int a[N + 7], b[N + 7];
memset(a, 0, sizeof a);
for (int k = 0; k < n; ++ k) a[k + 1] = a[k] + (j >> k & 1);
b[0] = 0;
for (int k = 1; k <= n; ++ k) b[k] = max(max(a[k], b[k - 1]), a[k - 1] + (c == t[k]));
int stt = 0;
for (int k = 0; k < n; ++ k) if (b[k + 1] - b[k]) stt |= 1 << k;
trans[j][c] = stt;
}
static int f[(1 << N) + 7], g[(1 << N) + 7];
memset(f, 0, sizeof f); f[0] = 1;
for (int i = 0; i < m; ++ i)
{
memset(g, 0, sizeof g);
for (int j = 0; j < 1 << n; ++ j) if (f[j]) for (int c = 1; c <= 4; ++ c)
g[trans[j][c]] = (g[trans[j][c]] + f[j]) % MOD;
swap(f, g);
}
static int ans[N + 7];
memset(ans, 0, sizeof ans);
for (int i = 0; i < 1 << n; ++ i)
{
int cnt = 0;
for (int tmp = i; tmp; tmp >>= 1) if (tmp & 1) ++ cnt;
ans[cnt] = (ans[cnt] + f[i]) % MOD;
}
for (int i = 0; i <= n; ++ i) printf("%d\n", ans[i]);
}
}

posted @ 2017-10-07 08:33  Zeonfai  阅读(140)  评论(0编辑  收藏  举报