题解:http://blog.youkuaiyun.com/lych_cys/article/details/51078401
令f[i][j][k]表示到第i位,状态为j,第i位为k的方案数。其中状态0表示之前没有k个B和k个W;1表示只有k个B;2表示之前有k个B和k个W。转移的时候只需要得到这一位填某一个字母的情况下会不会产生新的k个连续串,然后该加的地方加上,改去掉重复方案的去掉即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#define P 1000000007
using namespace std;
typedef long long ll;
int n,k;
ll f[1000005][3][2],sw[1000005],sb[1000005];
char ch[1000005];
int main()
{
int tmp;
scanf("%d%d",&n,&k);
ch[1]=getchar(); while (ch[1]<'A' || ch[1]>'Z') ch[1]=getchar();
for (int i=1;i<=n;i++)
{
if (i>1) ch[i]=getchar();
sb[i]=sb[i-1]; sw[i]=sw[i-1];
if (ch[i]=='B') sb[i]++;
else if (ch[i]=='W') sw[i]++;
}
f[0][0][1]=1;
for (int i=1;i<=n;i++)
{
if (ch[i]!='W')
{
if (i>=k && ch[i-k]!='B' && sw[i]==sw[i-k])
tmp=f[i-k][0][1];
else
tmp=0;
(((f[i][0][0]=f[i-1][0][0]+f[i-1][0][1]-tmp)%=P)+=P)%=P;
(((f[i][1][0]=f[i-1][1][0]+f[i-1][1][1]+tmp)%=P)+=P)%=P;
(((f[i][2][0]=f[i-1][2][0]+f[i-1][2][1])%=P)+=P)%=P;
}
if (ch[i]!='B')
{
if (i>=k && ch[i-k]!='W' && sb[i]==sb[i-k])
tmp=f[i-k][1][0];
else
tmp=0;
(((f[i][0][1]=f[i-1][0][0]+f[i-1][0][1])%=P)+=P)%=P;
(((f[i][1][1]=f[i-1][1][0]+f[i-1][1][1]-tmp)%=P)+=P)%=P;
(((f[i][2][1]=f[i-1][2][0]+f[i-1][2][1]+tmp)%=P)+=P)%=P;
}
}
printf("%lld\n",(f[n][2][0]+f[n][2][1])%P);
return 0;
}