考虑计算LCS的DP过程,设f[i][j]表示T串的前i项与S串的前j项的LCS,则
若T[i]==S[j],则f[i][j]=f[i-1][j-1]+1
否则f[i][j]=max(f[i-1][j],f[i][j-1])
对于固定的i,f[i][j]只可能为f[i][j-1]或f[i][j-1]+1,把这个差值用二进制表示成状态。
先预处理出每个状态后面加了一个字符后会到达什么状态,然后进行状压DP即可。
时间复杂度$O(m2^n)$。
#include<cstdio>
#include<cstring>
const int N=15,P=1000000007;
int T,n,m,i,j,k,x,a[N+1],f[N+1],g[N+1],v[1<<N][4],F[2][1<<N],ans[N+1];char s[N+1];
inline void up(int&a,int b){a+=b;if(a>=P)a-=P;}
void work(){
scanf("%s%d",s+1,&m);n=std::strlen(s+1);
for(i=1;i<=n;i++){
if(s[i]=='A')a[i]=0;
if(s[i]=='G')a[i]=1;
if(s[i]=='T')a[i]=2;
if(s[i]=='C')a[i]=3;
}
for(i=0;i<1<<n;i++){
for(j=0;j<n;j++)f[j+1]=f[j]+(i>>j&1);
for(j=0;j<4;j++){
for(k=1;k<=n;k++)if(a[k]==j)g[k]=f[k-1]+1;else g[k]=f[k]>g[k-1]?f[k]:g[k-1];
for(v[i][j]=0,k=1;k<=n;k++)if(g[k]>g[k-1])v[i][j]|=1<<(k-1);
}
}
for(j=0;j<1<<n;j++)F[0][j]=0;
for(F[0][0]=1,i=x=0;i<m;i++,x^=1){
for(j=0;j<1<<n;j++)F[x^1][j]=0;
for(j=0;j<1<<n;j++)if(F[x][j])for(k=0;k<4;k++)up(F[x^1][v[j][k]],F[x][j]);
}
for(i=0;i<=n;i++)ans[i]=0;
for(i=0;i<1<<n;i++)up(ans[__builtin_popcount(i)],F[x][i]);
for(i=0;i<=n;i++)printf("%d\n",ans[i]);
}
int main(){
for(scanf("%d",&T);T--;work());
return 0;
}