Consider calculating the DP process of the LCS, set F[I][J] to represent the first I item of the T string and the LCS of the first J of the S string, then
If T[I]==S[J], then f[i][j]=f[i-1][j-1]+1
Otherwise F[i][j]=max (F[i-1][j],f[i][j-1])
For fixed i,f[i][j] only possible for f[i][j-1] or f[i][j-1]+1, this difference is represented as a state in binary notation.
Pre-processing each state after the addition of a character will reach what state, and then the pressure DP can be.
Time complexity $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;}
Bzoj3864:hero Meet Devil