CF1476E. Pattern Matching

CF1476E Pattern Matching

原题链接

描述

有 n 个模式串 p[n],m 个字符串 s[n] 和对应的数字 \(mk_i\) ,每个模式串和字符串包含 k 个字符,(包含正常字符和下划线,其中下划线能匹配任意字符),要求模式串的一个排列使得,第 i 个字符串第一个匹配到的模式串为 \(p[mk_i]\)

思路

首先预处理所有字符串能匹配的模式串,即将对应的字符转化为下划线,找出其在模式串中的位置,如果位置中不包含 \(mk_i\),显然不能找到,否则用拓扑排序的方式将 mk 连边到所有除 mk 之外的下标,输出拓扑序即可。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, m, k;
    queue<int> q;
    scanf("%d%d%d", &n, &m, &k);
    map<string, int> mp;
    vector<vector<int>> adj(n);
    vector<int> ind(n, 0);
    for (int i = 0; i < n; i++) {
        string str;
        cin >> str;
        mp[str] = i;
    }
    bool ck = false;
    for (int i = 0; i < m; i++) {
        string str;
        cin >> str;
        int mk;
        cin >> mk;
        mk--;
        bool flag = false;
        if (ck) continue;

        for (int j = 0; j < (1 << k); j++) {
            string tmp = str;
            for (int x = 0; x < k; x++)
                if ((j >> x) & 1) tmp[x] = '_';
            if (mp.count(tmp))
                if (mp[tmp] == mk)
                    flag = true;
                else {
                    adj[mk].push_back(mp[tmp]);
                    ind[mp[tmp]]++;
                }
        }
        if (!flag) ck = true;
    }
    if (ck)
        puts("NO");
    else {
        vector<int> res;
        for (int i = 0; i < n; i++)
            if (!ind[i]) q.push(i);
        while (q.size()) {
            int u = q.front();
            q.pop();
            res.push_back(u);
            for (int v : adj[u]) {
                ind[v]--;
                if (!ind[v]) {
                    q.push(v);
                }
            }
        }
        if (res.size() == n) {
            puts("YES");
            for (int it : res) cout << it + 1 << " ";
        } else {
            puts("NO");
        }
    }
    return 0;
}
posted @ 2021-02-01 19:12  ans20xx  阅读(122)  评论(0)    收藏  举报