把LCS当成子串 看样例看了一年
这几天特别颓废啊【滑稽
…先考虑LCS的求法,以及给出的字符串长度,显然是需要状压的
对于求LCS的时候用的数组 dp[i][j]
把dp[i]差分之后,差分数组里只会有0和1,显然可以把这个东西状压了
然后又发现,对于每个 i ,dp数组只与dp[i-1]有关
于是可以用trans[s][ch] 表示在s状态的dp数组后面接字符ch可以转移到的状态 ,然后枚举未定数组的每一位的状态和转移就好了
反正比我写的好的题解多到不知道哪里去了【滑稽】
多组数据 忘记清空out数组WA了一把
#include<bits/stdc++.h>
#define MAXN 16
#define MAXM 1005
#define MOD 1000000007
using namespace std; int T,n,m;
char s[MAXN];
int trans[1<<MAXN][4];
int f[MAXN] , g[MAXN];
int ans[2][1<<MAXN];
int out[MAXN];
inline void work(){
scanf("%s%d",s,&m);
n = strlen(s);
for(int i=0;i<n;++i){
if(s[i]=='A') s[i] = 0;
if(s[i]=='T') s[i] = 1;
if(s[i]=='C') s[i] = 2;
if(s[i]=='G') s[i] = 3;
}
int maxs = 1<<n;
for(int o=0;o<maxs;++o){
f[0] = o&1;
for(int i=1;i<n;++i) f[i] = ((o>>i)&1) + f[i-1];
for(int i=0;i<4;++i){
memset(g,0,sizeof g);
for(int j=0;j<n;++j)
if(s[j]==i) g[j] = f[j-1] + 1;
else g[j] = max(g[j-1],f[j]);
int aim = 0;
for(int j=0;j<n;++j)
if(g[j]==g[j-1]+1)
aim |= 1<<j;
trans[o][i] = aim;
}
}
int now = 1;
memset(ans,0,sizeof ans);
ans[now^1][0] = 1;
for(int i=1;i<=m;++i,now = i&1){
for(int j=0;j<4;++j)
for(int o=0;o<maxs;++o)
(ans[now][trans[o][j]] += ans[now^1][o]) %= MOD;
memset(ans[now^1],0,sizeof ans[now^1]);
}
now^=1;
memset(out,0,sizeof out);
for(int o=0;o<maxs;++o) (out[__builtin_popcount(o)] += ans[now][o]) %= MOD;
for(int i=0;i<=n;++i) printf("%d\n",out[i]);
}
int main(){
for(scanf("%d",&T);T;--T) work();
return 0;
}