sgu 552 Database Optimization

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  k i (1 ≤  k i ≤ 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  key 1key 2,...,  key lwith the values  value 1value 2,...,  value l 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 · 10 4) — the number of objects. Following  n lines describe objects by their properties. Each line contains the integer  k i (1 ≤  k i ≤ 4) followed by  k i tokens in the form of  key i,j= value i,j separated by a single space. Both  key i,j and  value i,j consist of digits and lowercase Latin letters. The  key i,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 ≤ 10 5) — the number of queries. The following  mlines describe the queries. Each line contains a single integer  l i (the number of properties that describe the  i-th query) followed by  l i (1 ≤  l i ≤ 4) tokens  key i,j= value i,j separated by a single space, where  key i,j and  value i,jconsist of digits and lowercase Latin letters. The  key i,j are distinct for each query.

Lengths of  key i,j and  value i,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. 

Sample Input

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

题意 :   给n个关键字 , 然后再给m个关键字是可以任意组合在一起的,问,能在n个关键字(每行也可以任意组合在一起)里 查询出多少个 .



#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <iostream>
#include <map> 
using namespace std;


map<string,int>mp;


int N, M;
string str[4];       //  每个元素 是一个字符串 .


int main() {
    while (cin >> N) {
        int x;
        mp.clear();                            //初始化,清空map
        for (int i = 0; i < N; ++i) {
            cin >> x;
            for (int j = 0; j < x; ++j) {
                cin >> str[j];
            }
            sort(str, str+x);               //升序排序
            int mask = 1 << x;              //利用二进制枚举所有的关键字的组合.
            for (int j = 0; j < mask; ++j) {
                string tmp;
                for (int k = 0; k < 4; ++k) {
                    if (j & (1 << k)) {
                        tmp += " " + str[k];
                    }
                }
                ++mp[tmp];                  //得到的一个组合,数量加1
            }
        }
        cin >> M;
        while (M--) {
            cin >> x;
            for (int i = 0; i < x; ++i) {
                cin >> str[i];
            }
            sort(str, str+x);                         //要查询的关键字 也升序排序
            string tmp;
            for (int i = 0; i < x; ++i) {
                tmp += " " + str[i];            
            }
            printf("%d\n", mp[tmp]);                   //直接查找,这个组合的关键字有多少个
        }
    }
    return 0;
}


 . .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值