题意:中文
首先吐槽一下这道题的数据太水了,赛后看别人的代码很多连样例都过不了的竟然过了这道题。
思路:这道题可以看成是判断密码锁和密码是否存在最长公共子序列。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+50;
char s[maxn];
bool vis[maxn][maxn];
int n,m,q,f[maxn][maxn];
int main(){
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
vis[i][s[j]]=true;///记录每一个密码转盘出现的字符
}
}
for(int i=0;i<q;i++){///做q次lca
scanf("%s",s+1);///这里注意要腾出一格来初始化,因为首个密码位置可能为"#‘
int len=strlen(s+1);
if(len>n){
printf("NO\n");
continue;
}
memset(f,0,sizeof(f));
f[0][0]=1;
for(int j=1;j<=n;j++)
for(int k=0;k<=len;k++){
if(vis[j]['#']) f[j][k]|=f[j-1][k];///判断是否存在,'|'取并集
if(vis[j][s[k]]) f[j][k]|=f[j-1][k-1];///可以配对成功当且晋档这个位置为'#'或目标字符,二者取并集
}
if(f[n][len]) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
总结:这道题做的时候第一时间竟然没想到lcs。。。
以后碰到要求两个字符串有相同(不连续)部分的题目时要想到lca