Time Limit: 4 Sec
Memory Limit: 64 MB
Description
Input
本题包含多组数据。
第一行:一个整数T,表示数据的个数。
对于每组数据:
第一行:两个整数,N和K(含义如题目表述)。
接下来N行:每行一个字符串。
T ≤ 5,M ≤ 15,字符串长度≤ 50。
题目分析
d
p
[
i
]
[
s
]
dp[i][s]
dp[i][s]表示匹配长度为
i
i
i,匹配的字符串状态为s的方案数
初始化
d
p
[
0
]
[
(
1
<
<
n
)
−
1
]
=
1
dp[0][(1<<n)-1]=1
dp[0][(1<<n)−1]=1,直接枚举下一位字符转移即可
d
p
[
i
+
1
]
[
s
′
]
+
=
d
p
[
i
]
[
s
]
dp[i+1][s^{'}]+=dp[i][s]
dp[i+1][s′]+=dp[i][s]
忘了
d
p
[
i
]
[
s
]
=
0
dp[i][s]=0
dp[i][s]=0的时候可以跳过枚举,被卡常了好久。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int mod=1e6+3;
const int maxn=16;
int T,n,k;
int dp[55][1<<maxn];
char ss[maxn][55];
int main()
{
T=read();
while(T--)
{
memset(dp,0,sizeof(dp));
n=read();k=read();
for(int i=1;i<=n;++i)
scanf("%s",ss[i]+1);
int len=strlen(ss[1]+1),lim=(1<<n)-1;
dp[0][lim]=1;
for(int i=0;i<len;++i)
for(int s=0;s<=lim;++s)
{
if(!dp[i][s]) continue;
for(int c=1;c<=26;++c)
{
int nxt=0;
for(int k=1;k<=n;++k)
if(ss[k][i+1]=='?'||ss[k][i+1]-'a'+1==c)
nxt|=(1<<k-1);
dp[i+1][nxt&s]+=dp[i][s]; dp[i+1][nxt&s]%=mod;
}
}
int ans=0;
for(int s=1;s<=lim;++s)
{
int cnt=0;
for(int j=0;j<n;++j)
if(s&(1<<j)) cnt++;
if(cnt==k) ans=(ans+dp[len][s])%mod;
}
printf("%d\n",ans);
}
return 0;
}