#include #include #include #include #include #include struct node { bool isLeaf {false}; node* sons[10] {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; int count {0}; }; int N; int Q; std::vector undamaged; std::vector undamagedReversed; node* trie; node* trieReversed; int num_to_i(char n) { return n - '0'; } node* mk_trie(const std::vector& nums) { node* root = new node(); for (const std::string& num : nums) { node* curr = root; for (int numpos = 0; numpos < 9; ++numpos) { int i = num_to_i(num[numpos]); if (! curr->sons[i]) { curr->sons[i] = new node(); } curr = curr->sons[i]; } curr->isLeaf = true; } return root; } void calculate_counts(node* root) { if (root->isLeaf) { root->count = 1; } for (int k = 0; k < 9; ++k) { if (root->sons[k]) { calculate_counts(root->sons[k]); root->count += root->sons[k]->count; } } } int may_correspond_count(const std::string& ns, int npos, node* pos) { if (pos->isLeaf) { return 1; } char c = ns[npos]; if (c == '?') // coffee { int res = 0; for (int k = 0; k < 9; ++k) { if (pos->sons[k]) { res += may_correspond_count(ns, npos + 1, pos->sons[k]); } } return res; } else { int i = num_to_i(c); if (! pos->sons[i]) { return 0; } return may_correspond_count(ns, npos + 1, pos->sons[i]); } } int up_to_star(node* trieNode, const std::string& line) { int i = 0; while (line[i] != '*') { trieNode = trieNode->sons[num_to_i(line[i])]; ++i; } return trieNode->count; } std::string preprocess(const std::string& line) { auto it = std::find(begin(line), end(line), '*'); if (it == end(line)) { return line; } int pos = std::distance(begin(line), it); std::string head = line.substr(0, pos); std::string tail = line.substr(pos + 1); std::string glue(9 - (line.size() - 1), '?'); return head + glue + tail; } int may_correspond_dispatch(const std::string& line) { if (line == "*") { return N; } auto it = std::find(begin(line), end(line), '*'); if (it == end(line)) { return may_correspond_count(line, 0, trie); } else { if (line.front() == '*') { std::string tmpline = line; std::reverse(begin(tmpline), end(tmpline)); return up_to_star(trieReversed, tmpline); } else if (line[line.size() - 1] == '*') { return up_to_star(trie, line); } else { std::string tmpline = preprocess(line); std::string tmpRevLine = tmpline; std::reverse(begin(tmpRevLine), end(tmpRevLine)); int pos = std::distance(begin(line), it); if (pos < 5) { return may_correspond_count(tmpRevLine, 0, trieReversed); } else { return may_correspond_count(tmpline, 0, trie); } } } } int main() { std::cin >> N; undamaged.reserve(N); for (int k = 0; k < N; ++k) { std::string line; std::cin >> line; undamaged.emplace_back(line); std::reverse(begin(line), end(line)); undamagedReversed.emplace_back(std::move(line)); } trie = mk_trie(undamaged); trieReversed = mk_trie(undamagedReversed); calculate_counts(trie); calculate_counts(trieReversed); std::cin >> Q; for (int k = 0; k < Q; ++k) { std::string line; std::cin >> line; std::cout << may_correspond_dispatch(line) << std::endl; } return 0; }