CF852G Bathroom terminal题解

原题传送门

题目大意

给定 \(N\) 个最大长度不超过 \(L\) 的字符串与 \(M\) 个模式串。模式串中,有若干个 '?' 字符,可以代表 'a~e' 中任意一个字符与字符 ' '。对于每一个模式串,要求输出与之匹配的单词数。

题目分析

因为每个模式串中 '?' 字符的数量不会超过 \(3\) 个,所以我们考虑找到串中 '?' 的的位置,暴力枚举它们所有可能情况。在枚举的过程中,可以按照它们各自 '?' 字符的数量分类讨论,分别枚举它们可能的情况,同时,为降低枚举 ' ' 的困难,不妨将其记作字符 'f',最终利用 mapunordered_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;
}

希望这篇题解对你有帮助

AC记录

posted @ 2025-01-13 13:37  vanueber  阅读(13)  评论(0)    收藏  举报