卧薪尝胆,厚积薄发。
      
    
            Hero meet devil
        
        
        Description:
一个字符串
$S$
只由
$AGCT$
组成,对于每个
$i$
,求只由
$AGCT$
组成的长为
$m$
的字符串
$T$
个数,使得
$LCS(T,S)=i$
。 
$1\leqslant m\leqslant 10^3,1\leqslant |S|\leqslant 15$
Solution:
考虑求
$LCS$
那个
$DP$
:
$$
f[i][j]=\max(\max(f[i-1][j],f[i][j-1]),f[i-1][j-1]+[T[i]=S[j]])
$$
如果我们只看第二维的话会发现第二维单调不降,并且相邻两个只差
$1$
,那么我们考虑把差分数组状压起来,然后每次往
$T$
后面加一个字符,预处理子
$DP$
每个状态往后面加一个字符
$c$
能转移到的状态计数即可。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
	register int res = 0,f = 1;register char c = getchar();
	while(!isdigit(c)){if(c == '-')f = -1;c = getchar();}
	while(isdigit(c))res = (res << 1) + (res << 3) + c - '0',c = getchar();
	return res * f;
}
int n,m;
#define MAXN 1010
#define MAXM 17
#define MAX 15
char c[MAXM];
int toint(char c)
{
	if(c == 'A')return 0;if(c == 'G')return 1;
	if(c == 'C')return 2;if(c == 'T')return 3;
}
int S[MAXM];
int g[1 << MAX][4];
int dp[2][MAXN];
int bit(int s,int i){return ((s >> (i - 1)) & 1);}
int f[2][1 << MAX];
int ans[MAXM];
#define MOD 1000000007
void work()
{
	scanf("%s",c + 1);
	m = strlen(c + 1);
	scanf("%d",&n);
	for(int i = 1;i <= m;++i)S[i] = toint(c[i]);
	for(int i = 0;i < (1 << m);++i)
	{
		for(int x = 0;x < 4;++x)
		{
			for(int k = 1;k <= m;++k)dp[0][k] = dp[0][k - 1] + bit(i,k);
			for(int k = 1;k <= m;++k)dp[1][k] = max(max(dp[0][k],dp[1][k - 1]),dp[0][k - 1] + (x == S[k]));
			int s = 0;
			for(int k = 1;k <= m;++k)s |= ((dp[1][k] - dp[1][k - 1]) << (k - 1));
			g[i][x] = s;
		}
	}
	memset(f,0,sizeof(f));
	int cur = 0;
	f[0][0] = 1;
	for(int i = 1;i <= n;++i)
	{
		cur ^= 1;
		memset(f[cur],0,sizeof(f[cur]));
		for(int s = 0;s < (1 << m);++s)
		{
			for(int x = 0;x < 4;++x)
			{
				f[cur][g[s][x]] = (f[cur][g[s][x]] + f[cur ^ 1][s]) % MOD;
			}
		}
	}
	memset(ans,0,sizeof(ans));
	for(int s = 0;s < (1 << m);++s)
	{
		int sum = 0;
		for(int k = 1;k <= m;++k)sum += (s >> (k - 1)) & 1;
		ans[sum] = (ans[sum] + f[cur][s]) % MOD;
	}
	for(int i = 0;i <= m;++i)printf("%d\n",ans[i]);	
	return;
}
int main()
{
	int testcases = rd();
	while(testcases--)work();
	return 0;
}
 In tag:
DP-DP套DP
          In tag:
DP-DP套DP 
          
        
        Copyright © 2020
        
          wjh15101051
        
      
      ღゝ◡╹)ノ♡
     Date: Sat Mar 30 11:40:02 CST 2019
          Date: Sat Mar 30 11:40:02 CST 2019
           In Category:
          In Category:
           
         Timeline
            Timeline
           About
            About
           Toolbox
            Toolbox
           Friends
              Friends