CF852G Bathroom terminal题解
题目大意
给定 \(N\) 个最大长度不超过 \(L\) 的字符串与 \(M\) 个模式串。模式串中,有若干个 '?' 字符,可以代表 'a~e' 中任意一个字符与字符 ' '。对于每一个模式串,要求输出与之匹配的单词数。
题目分析
因为每个模式串中 '?' 字符的数量不会超过 \(3\) 个,所以我们考虑找到串中 '?' 的的位置,暴力枚举它们所有可能情况。在枚举的过程中,可以按照它们各自 '?' 字符的数量分类讨论,分别枚举它们可能的情况,同时,为降低枚举 ' ' 的困难,不妨将其记作字符 'f',最终利用 map 或 unordered_map 统计答案时对于字符串再做分离处理,在 2000ms 的时限内可以通过,具体实现见代码部分。
代码部分
#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<string, int> check;
string st;
int n, m, ans = 0;
string get(string str) //对枚举出的一种字符串做‘ ’分离操作
{
string ret;
for (int i = 0; i < str.size(); i++)
{
if (str[i] != 'f')
ret += str[i];
}
return ret;
}
void work(string ss)
{
vector<int> pos; //记录?的位置
for (int i = 0; i < ss.size(); i++)
{
if (ss[i] == '?')
pos.push_back(i);
}
map<string, int> vis;
switch (pos.size()) //分4种情况讨论
{
case 0:
{
if (check[ss] != 0)
ans++;
break;
}
case 1:
{
string t = ss;
for (int i = 0; i <= 5; i++) //记'f'为' ',枚举到'f'
{
t[pos[0]] = 'a' + i;
string lst = get(t);
if (check[lst] != 0 && vis[lst] == 0)
{
vis[lst]++;
ans += check[lst];
}
}
break;
}
case 2:
{
string t = ss;
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 5; j++)
{
t[pos[0]] = 'a' + i;
t[pos[1]] = 'a' + j;
string lst = get(t);
if (check[lst] != 0 && vis[lst] == 0)
{
vis[lst]++;
ans += check[lst];
}
}
}
break;
}
case 3:
{
string t = ss;
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 5; j++)
{
for (int k = 0; k <= 5; k++)
{
t[pos[0]] = 'a' + i;
t[pos[1]] = 'a' + j;
t[pos[2]] = 'a' + k;
string lst = get(t);
if (check[lst] != 0 && vis[lst] == 0)
{
vis[lst]++;
ans += check[lst];
}
}
}
}
break;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
cin >> st;
check[st]++;
}
for (int i = 1; i <= m; i++)
{
ans = 0;
cin >> st;
work(st);
printf("%d\n", ans);
}
return 0;
}
希望这篇题解对你有帮助

浙公网安备 33010602011771号