p552.cpp
======================
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n;
vector<vector<pair<string, string>>> objects;

vector<pair<string, string>> get_object(int cnt) {
    vector<pair<string, string>> obj;
    while(cnt--) {
        string s;
        cin >> s;
        vector<string> xy = {""};
        for(char c: s) {
            if(c == '=') {
                xy.push_back("");
                continue;
            }
            xy.back().push_back(c);
        }

        obj.push_back({xy[0], xy[1]});
    }
    return obj;
}

vector<pair<string, string>> canonize(vector<pair<string, string>> obj) {
    sort(obj.begin(), obj.end());
    return obj;
}

void read() {
    cin >> n;
    objects.resize(n);
    for(int i = 0; i < n; i++) {
        int cnt;
        cin >> cnt;
        objects[i] = canonize(get_object(cnt));
    }
}

string total_canonize(vector<pair<string, string>> obj) {
    string res;
    for(auto [x, y]: obj) {
        res += x + '=' + y + ',';
    }
    return res;
}

void solve() {
    unordered_map<string, int> cnt;
    for(int i = 0; i < n; i++) {
        for(int mask = 0; mask < (1 << objects[i].size()); mask++) {
            vector<pair<string, string>> obj;
            for(int j = 0; j < objects[i].size(); j++) {
                if(mask & (1 << j)) {
                    obj.push_back(objects[i][j]);
                }
            }
            cnt[total_canonize(obj)]++;
        }
    }

    int q;
    cin >> q;
    while(q--) {
        int c;
        cin >> c;
        vector<pair<string, string>> obj = get_object(c);
        obj = canonize(obj);
        cout << cnt[total_canonize(obj)] << '\n';
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}

=================
statement.txt
======================
552. Database optimization
Time limit per test: 3 second(s)
Memory limit: 262144 kilobytes
input: standard
output: standard



Alex worked at a big IT-company called Macrohard. Once, when he faced a large amount of data, he decided to leave this company and develop his own database which would be much better than all existing ones. When he was done with this he realized that the performance of some database queries might be improved. Alex uses AQL (Alex Query Language) which accidentally turned out to be exactly the same as the popular SQL. One of the most important problems he faced was the following.

Consider n objects. The i-th object has ki (1 ≤ ki ≤ 4) properties in the form of key=value. Any object can't have two or more properties with the same key. Alex needs to improve the performance of the following query:

SELECT COUNT(*) FROM Objects WHERE key1=value1 AND...  AND keyl=valuel
(1 ≤ l ≤ 4, all keys are distinct)
This means that Alex's database has to find the number of objects which have properties key1, key2,..., keyl with the values value1, value2,..., valuel respectively. Even if an object has extra properties it should be counted.

Your task is to help Alex to write an efficient program to process such queries.

Input
The first line of the input contains a single integer n (1 ≤ n ≤ 5 · 104) — the number of objects. Following n lines describe objects by their properties. Each line contains the integer ki (1 ≤ ki ≤ 4) followed by ki tokens in the form of keyi,j=valuei,j separated by a single space. Both keyi,j and valuei,j consist of digits and lowercase Latin letters. The keyi,j are distinct for each object. It is possible that different objects have exactly the same set of properties.

The next line of the input contains a single integer m (1 ≤ m ≤ 105) — the number of queries. The following m lines describe the queries. Each line contains a single integer li (the number of properties that describe the i-th query) followed by li (1 ≤ li ≤ 4) tokens keyi,j=valuei,j separated by a single space, where keyi,j and valuei,j consist of digits and lowercase Latin letters. The keyi,j are distinct for each query.

Lengths of keyi,j and valuei,j both for objects and queries are between 1 and 5 characters inclusive.

Output
Print m lines, the i-th line should contain the result of the i-th query.

Example(s)
sample input
sample output
4
3 width=5 ht=3 len=10
2 name=circ rad=5
2 name=circ rad=5
3 name=sqr width=5 ht=3
4
2 ht=3 width=5
1 name=circ
1 name=sqr
2 width=5 ht=03
2
2
1
0

=================
