• [CF1476E] Pattern Matching


    [CF1476E] Pattern Matching - Trie,拓扑排序

    Description

    给定 (n) 个模式串 (p_i)(m) 个字符串 (s_i),其中 (p_i) 两两不同。每个模式串和字符串都包含 (k) 个字符。其中模式串中可以含通配符(用下划线表示,可以匹配任何字符),剩余字符都为小写英文字母。同时给定 (n) 个数 (mt_i),要求重新排列模式串使得 (s_j) 匹配到的第一个模式串为 (p_{mt_j})。请判断是否存在排列方案满足如上要求,能的话请输出方案。

    Solution

    拓扑排序,需要预处理每个 str 匹配了哪些 pat,对 pat 建立 Trie 树即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1e5 + 5;
    
    int n_pat, n_str, len;
    
    string pat[N], str[N];
    int lim[N];
    
    int ind = 1, ch[N * 5][27], val[N * 5], vis[N], deg[N];
    
    vector<int> g[N];
    vector<int> seq;
    
    void insert(string s, int id)
    {
        int p = 1;
        for (int i = 0; i < s.size(); i++)
        {
            int c = s[i] - 'a';
            if (s[i] == '_')
                c = 26;
            if (ch[p][c] == 0)
                ch[p][c] = ++ind;
            p = ch[p][c];
        }
        val[p] = id;
    }
    
    void find_matches(string s, int i, int p, vector<int> &ans)
    {
        if (p == 0)
        {
            return;
        }
        if (i == len)
        {
            if (val[p])
                ans.push_back(val[p]);
        }
        else
        {
            find_matches(s, i + 1, ch[p][s[i] - 'a'], ans);
            find_matches(s, i + 1, ch[p][26], ans);
        }
    }
    
    void dfs(int p)
    {
        vis[p] = 1;
        for (int q : g[p])
        {
            if (vis[q])
                continue;
            dfs(q);
        }
        seq.push_back(p);
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n_pat >> n_str >> len;
    
        for (int i = 1; i <= n_pat; i++)
        {
            cin >> pat[i];
            insert(pat[i], i);
        }
    
        for (int i = 1; i <= n_str; i++)
        {
            cin >> str[i] >> lim[i];
            vector<int> matches;
            find_matches(str[i], 0, 1, matches);
            int flag = 0;
            for (auto j : matches)
            {
                if (j == lim[i])
                {
                    flag = 1;
                }
                else
                {
                    g[lim[i]].push_back(j);
                    deg[j]++;
                }
            }
            if (flag == 0)
            {
                cout << "NO" << endl;
                return 0;
            }
        }
    
        // toposort
        for (int i = 1; i <= n_pat; i++)
        {
            if (deg[i] || vis[i])
                continue;
            dfs(i);
        }
        reverse(seq.begin(), seq.end());
    
        set<int> s;
        if (seq.size())
            for (int i = seq.size() - 1; i >= 0; i--)
            {
                s.insert(seq[i]);
                for (int q : g[seq[i]])
                {
                    if (s.find(q) == s.end())
                    {
                        cout << "NO" << endl;
                        return 0;
                    }
                }
            }
    
        if (seq.size() != n_pat)
        {
            cout << "NO" << endl;
        }
        else
        {
            cout << "YES" << endl;
            for (auto i : seq)
                cout << i << " ";
            cout << endl;
        }
    }
    
  • 相关阅读:
    ArrayList源代码深入剖析
    java线程基础巩固---wait和sleep的本质区别是什么,深入分析(面试常见问题)
    设计模式相关面试问题-模板方法
    设计模式相关面试问题-适配器
    设计模式相关面试问题-单例
    python-面向对象-10-单例
    python-面向对象-11-异常
    ping
    arp欺骗
    list的方法、操作
  • 原文地址:https://www.cnblogs.com/mollnn/p/14511608.html
Copyright © 2020-2023  润新知