题意

给n个需要忽视的目录,m个需要保护的目录,求gitignore的最小行数

Solution

用保护去检索ignore。

#include <bits/stdc++.h>
using namespace std;
int t, n, m;
vector<string> v1, v2;
set<string> prt, vis;
int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> t;
    while (t--) {
        cin >> n >> m;
        string s;
        v1.clear(), v2.clear(), vis.clear(), prt.clear();
        for (int i = 0; i < n; i++) cin >> s, v1.push_back(s);
        for (int i = 0; i < m; i++) cin >> s, v2.push_back(s);
        for (int i = 0; i < m; i++) {
            string s = "";
            for (char &c : v2[i]) {           //建立保护清单
                if (c == '/') prt.insert(s);  //所有的父级目录都被保护
                s += c;
            }
        }
        int ans = n;  //假设全都单独写入gitignore
        for (int i = 0; i < n; i++) {
            string s = "";
            for (char &c : v1[i]) {
                if (c == '/') {
                    if (!prt.count(s)) {  //没有被保护
                        if (vis.count(s)) --ans;  //存在同级目录
                        else vis.insert(s);
                        break;  //子目录不再检索
                    }  //此处是一个贪心的最优:子目录可以,且父目录未被保护,肯定是父目录最优
                }
                s += c;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

map写法亦可

#include <bits/stdc++.h>
using namespace std;
int t, n, m;
vector<string> v1, v2;
map<string, bool> prt, vis;
int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> t;
    while (t--) {
        cin >> n >> m;
        string s;
        v1.clear(), v2.clear(), vis.clear(), prt.clear();
        for (int i = 0; i < n; i++) cin >> s, v1.push_back(s);
        for (int i = 0; i < m; i++) cin >> s, v2.push_back(s);
        for (int i = 0; i < m; i++) {
            string s = "";
            for (char &c : v2[i]) {
                if (c == '/') prt[s] = 1;
                s += c;
            }
        }
        int ans = n;
        for (int i = 0; i < n; i++) {
            string s = "";
            for (char &c : v1[i]) {
                if (c == '/') {
                    if (!prt[s]) {
                        if (vis[s]) --ans;
                        else vis[s] = 1;
                        break;
                    }
                }
                s += c;
            }
        }
        cout << ans << endl;
    }
    return 0;
}