传送门
大力动归。
设f[i][k][l][p]表示前i位,连续相同字母个数k个,连续相同种类字母l个,字母是p的方案数
然后大力dp一发就可以了。
#include<bits/stdc++.h>
using namespace std;
int C[2],E[2],n,hsh[30],a[20];
char s[20];
long long f[20][10][10][30],ans;
int main(){
scanf("%d%d%d%d%s",&E[1],&C[1],&E[0],&C[0],s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
a[i]=(s[i]=='*'?26:s[i]-'a');
hsh[0]=hsh[4]=hsh[8]=hsh[14]=hsh[20]=1;
for (int i=0;i<26;i++)
if (a[1]==26||a[1]==i) f[1][1][1][i]=1;
for (int i=2;i<=n;i++)
for (int ch=0;ch<26;ch++)
if (a[i]==26||a[i]==ch)
for (int la=0;la<26;la++)
if (a[i-1]==26||a[i-1]==la){
int p=hsh[ch],q=hsh[la];
if (p==q){
if (ch==la)
for (int c=2;c<=C[p];c++)
for (int e=2;e<=E[p];e++)
f[i][c][e][ch]+=f[i-1][c-1][e-1][la];
else
for (int c=2;c<=C[p];c++)
for (int e=1;e<=E[p];e++)
f[i][c][1][ch]+=f[i-1][c-1][e][la];
}
else
for (int c=1;c<=C[q];c++)
for (int e=1;e<=E[q];e++)
f[i][1][1][ch]+=f[i-1][c][e][la];
}
for (int i=0;i<26;i++)
if (a[n]==i||a[n]==26){
int p=hsh[i];
for (int c=1;c<=C[p];c++)
for (int e=1;e<=E[p];e++)
ans+=f[n][c][e][i];
}
printf("%lld",ans);
}