題目連接c++
題意:3d
給n長度的S串,對於0<=i<=|S|,有多少個長度爲m的T串,使得LCS(S,T) = i。blog
思路:it
理解的不是很透徹,先佔個坑。class
#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; }