传送门:codeforces 883E
题目大意:
给你一个长度为 n 的字符串 S,其中 * 代表未知的,其他的代表已知的。然后给你 m 个长度为 n 的字符串,未知处字符一定在这 m 个字符串里面。问存在多少个字符一定可以让一个未知字符变成已知字符。
思路:
这个题一开始题目就没理解透彻……给出的 m 个串中已知的部分竟然可以和给定的 S 字符串处不同……未知的部分也可能出现已知的字符……Orz……以上两种情况都算这个字符串是错误的。
所以先把错误的字符串去掉,也就是应该是未知部分出现已知字符的,或者是已知部分和主串 S 处不同的。然后遍历 a~z 26 个字符,如果字符未知并且在正确的字符串中都出现过,则答案 +1 。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<set>
using namespace std;
int main()
{
int i,j,n,m,len,vis[1010];
char c[3],s[55],t[1010][55];
set<char> st; //保存已知的字符
while(~scanf("%d",&n))
{
scanf("%s",s);
st.clear();
for(i=0;i<strlen(s);i++)
if(s[i]!='*') st.insert(s[i]); //保存已知字符
scanf("%d",&m);
memset(vis,0,sizeof(vis)); //判断字符串是否正确
for(i=0;i<m;i++)
{
scanf("%s",t[i]);
int f=1;
for(j=0;j<strlen(t[i]);j++)
if(s[j]=='*')
{ //如果未知处出现已知字符
if(st.count(t[i][j]))
{
f=0;
break;
}
}
else if(s[j]!=t[i][j])
{ //如果已知处和 S 不相同
f=0;
break;
}
if(f) vis[i]=1; //是正确的字符
}
int ans=0;
for(i=0;i<26;i++)
{ //遍历所有字符
c[0]='a'+i;
c[1]='\0';
if(st.count(c[0])) continue; //如果在 s中出现过
int f=1;
for(j=0;j<m;j++)
if(vis[j]&&strstr(t[j],c)==NULL)
{ //如果当前字符串是正确的且不包含当前字符
f=0;
break;
}
if(f) ans++;
}
printf("%d\n",ans);
}
return 0;
}