# BZOJ3864 Hero meet devil

BZOJ权限题

HDU

vjudge

### 题解

$dp$套$dp$。。。

$$lcs[i][j]=max \begin{cases} lcs[i-1][j-1]+1 & (t[i] = s[j]) \\ max(lcs[i-1][j],lcs[i][j-1]) & (t[i]\neq s[j]) \end{cases}$$

$$f[i][trans[S][\text{A/G/C/T}]] \text{+=}f[i-1][S]$$

### 代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x))
#define pcnt __builtin_popcount

const int maxn(1001), Mod(1e9 + 7), LEN(15);
char s[LEN + 1], S_now[] = "AGCT";
int a[LEN + 1], f[maxn][(1 << LEN) | 2], T, LIM, ans[maxn];
int trans[(1 << LEN) | 2][5], n, len, tmp[2][LEN + 1];

int Calc(int S, int c)
{
int ans = 0; clear(tmp, 0);
for(RG int i = 0; i < n; i++) tmp[0][i + 1] = tmp[0][i] + ((S >> i) & 1);
for(RG int i = 1; i <= n; i++)
{
int max = 0; if(a[i] == c) max = tmp[0][i - 1] + 1;
max = std::max(std::max(max, tmp[0][i]), tmp[1][i - 1]);
tmp[1][i] = max;
}
for(RG int i = 0; i < n; i++) ans += (1 << i) * (tmp[1][i + 1] - tmp[1][i]);
return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
file(cpp);
#endif
scanf("%d", &T);
while(T--)
{
clear(f, 0); clear(ans, 0);
scanf("%s", s + 1);
n = strlen(s + 1); LIM = (1 << n);
for(RG int i = 1; i <= n; i++)
for(RG int j = 0; j < 4; j++)
if(s[i] == S_now[j]) { a[i] = j + 1; break; }
scanf("%d", &len); f[0][0] = 1;
for(RG int i = 0; i < LIM; i++)
for(RG int j = 1; j <= 4; j++) trans[i][j] = Calc(i, j);
for(RG int i = 1; i <= len; i++)
for(RG int S = 0; S < LIM; S++)
for(RG int k = 1; k <= 4; k++)
f[i][trans[S][k]] = (f[i][trans[S][k]] + f[i - 1][S]) % Mod;
for(RG int S = 0; S < LIM; S++)
ans[pcnt(S)] = (ans[pcnt(S)] + f[len][S]) % Mod;
for(RG int i = 0; i <= n; i++) printf("%d\n", ans[i]);
}
return 0;
}

posted @ 2019-01-04 16:07  xgzc  阅读(105)  评论(0编辑  收藏  举报