题目描述:
小H在击败怪兽后,被一个密码锁挡住了去路
密码锁由N个转盘组成,编号为1~N,每个转盘有M个位置,每个位置上要么有一个小写字母,要么没有任何字符。一个密码能被转盘表示出,当且仅当指定每个转盘上面的某一个位置,然后将这些位置按照所属的转盘编号顺次连接(空位置直接忽略),可以得到这个密码
小H在击败怪兽后,被一个密码锁挡住了去路
密码锁由N个转盘组成,编号为1~N,每个转盘有M个位置,每个位置上要么有一个小写字母,要么没有任何字符。一个密码能被转盘表示出,当且仅当指定每个转盘上面的某一个位置,然后将这些位置按照所属的转盘编号顺次连接(空位置直接忽略),可以得到这个密码
小H并没有得到任何线索,因此只能猜,她一共猜了Q次,但并不知道自己猜的密码能否被表示出来,于是她向你求助
输入描述:
第1行,三个整数N,M,Q
第2~N+1行,每行一个长度为M的字符串,依次表示每个转盘上的字符
第N+2~N+Q+1行,每行一个长度不超过10000的字符串,表示小H猜的密码
2≤N,Q≤300,2≤M≤27,同一个转盘上每种字符最多出现一次
输出描述:
输出Q行,每行都是YES或NO,依次表示小H猜的每个字符串能否被表示出
输入样例:
3 2 3
a#
ab
bc
aa
bb
ba
输出样例:
NO
YES
NO
备注:‘#’代表空字符
题解:设dp[i][j]:表示匹配到第i个串和所猜的字符串的第j个字符的状态,然后直接转移即可。。。。
昨晚理解错题意了,以为猜的串里也有空字符。。。。。然后写了半天的字典树。。。太傻
#include<stdio.h>
#include<string.h>
char s[305][30],str[100005];
int dp[305][305],flag[305][305],n,m,q,len;
int main(void)
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]);
for(int j=0;j<m;j++)
{
if(s[i][j]=='#')
flag[i][26]=1;
else
flag[i][s[i][j]-'a']=1;
}
}
while(q--)
{
scanf("%s",str);
len=strlen(str);
memset(dp,0,sizeof(dp));
if(len>n)
{
printf("NO\n");
continue;
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=len;j++)
{
if(flag[i][26])
dp[i][j]|=dp[i-1][j];
if(j<len && flag[i][str[j]-'a'])
dp[i][j+1]|=dp[i-1][j];
}
if(dp[n][len])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}