卧薪尝胆,厚积薄发。
TJOI2018 游园会
Date: Sat Mar 30 11:36:55 CST 2019 In Category: NoCategory

Description:

给一个串 $S$ ,对于每个 $i$ 求出有多少个 $T$ 满足 $LCS(S,T)=i$ 并且 $T$ 中不出现连续子串 $NOI$ , $\Sigma=NOI$ 。
$1\leqslant n\leqslant 10^3,1\leqslant |S|\leqslant 15$

Solution:

显然的DP套DP,再加一维表示和NOI的匹配长度即可。

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 == 'N')return 0;if(c == 'O')return 1;
if(c == 'I')return 2;
}
int S[MAXM];
int g[1 << MAX][3][3];
int dp[2][MAXN];
int bit(int s,int i){return ((s >> (i - 1)) & 1);}
int f[2][1 << MAX][3];
int ans[MAXM];
#define MOD 1000000007
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",c + 1);
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 < 3;++x)
{
for(int l = 0;l < 3;++l)
{
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,len;
for(int k = 1;k <= m;++k)s |= ((dp[1][k] - dp[1][k - 1]) << (k - 1));
if(x == l)len = l + 1;
else if(x == 0)len = 1;
else len = 0;
if(len == 3)g[i][x][l] = -1;
else g[i][x][l] = s * 3 + len;
}
}
}
memset(f,0,sizeof(f));
int cur = 0;
f[0][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 < 3;++x)
{
for(int l = 0;l < 3;++l)
{
int t = g[s][x][l] / 3,len = g[s][x][l] % 3;
if(g[s][x][l] != -1)f[cur][t][len] = (f[cur][t][len] + f[cur ^ 1][s][l]) % 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;
for(int l = 0;l < 3;++l)ans[sum] = (ans[sum] + f[cur][s][l]) % MOD;
}
for(int i = 0;i <= m;++i)printf("%d\n",ans[i]);
return 0;
}
In tag: DP-DP套DP
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡