2023-03-3 LDAP

原题链接:

计算机软件能力认证考试系统

题解:

本来我的想法是对于每个表达式,都遍历一次用户判断是否满足该表达式,但最后超时了,只得了70分。

后来在网上看了不少博客,大多数都是采用bitset的做法,对于每个表达式中的逻辑表达式,不断递归拆分,拆分为2个基础表达式,然后分别求满足这2个基础表达式的用户,然后再回溯分别求交集或者并集即可,这样子就不需要对每个表达式都遍历一遍用户列表。

代码:

70分代码:
#pragma GCC optimize(2, 3, "Ofast", "inline")
#include<bits/stdc++.h>
using namespace std;
int n, m;
map<int, unordered_map<int, int>> v;//用户-(属性-值)
stack<int> dig;
stack<char> op;

bool judge(int a, char b, int c, int fir = 0) {
	if (b == ':') return v[fir][a] == c;
	else if (b == '~') return v[fir][a] != 0 && v[fir][a] != c;
	else if (b == '&') return a & c;
	else return a | c;
}

void eval(int dim) {//进行处理
	int num2 = dig.top();dig.pop();//第2个操作数
	int num1 = dig.top();dig.pop();//第1个操作数
	char p = op.top();op.pop();
	//计算结果
	if (p == ':' || p == '~') dig.push(judge(num1, p, num2, dim));
	else dig.push(judge(num1, p, num2));
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	cin >> n;
	for (int i = 1;i <= n;i++) {
		int DN, num;cin >> DN >> num;
		while (num--) {
			int a, b;cin >> a >> b;
			v[DN][a] = b;
		}
	}

	cin >> m;
	while (m--) {
		string s;cin >> s;
		for (auto k = v.begin();k != v.end();k++) {
			int dim = k->first;
			while (!dig.empty()) dig.pop();//清空数字栈和符号栈
			while (!op.empty()) op.pop();
			int len = s.size();
			for (int i = 0;i < len;i++) {
				if (isdigit(s[i])) {//数字入栈
					int x = 0, j = i;
					while (isdigit(s[j]) && j < len) {
						x = x * 10 + s[j] - '0';
						j++;
					}
					dig.push(x);
					i = j - 1;
				}
				//else if (s[i] == '(') op.push(s[i]);//左括号入栈
				else if (s[i] == ')') {//每匹配到一个右括号直接进行计算后入栈
					while (op.top() != '(')
						eval(dim);
					op.pop();//弹出左括号
				}
				else op.push(s[i]);//遇见其他符号,入栈即可
			}
			while (op.size()) eval(dim);
			if (dig.top()) cout << dim << " ";
		}
		cout << endl;
	}
}
100分代码:(转载自202303 CSP认证 | LDAP (bitset)-CSDN博客
#include<bits/stdc++.h>
using namespace std;
using PSS = pair<string, string>;
const int N = 3010;
int n, user[N];  //存储id(dn)
unordered_map<string, unordered_set<int> > hash_k;  //哪个用户具有特定的key
map<PSS, unordered_set<int>> hash_kv;   //哪个用户具有某个特定的key-value对
//这里不能用unordered_map,因为cpp中没有给pair做hash的函数,所以不能用pair作为unordered_map的key。

bitset<N> handle(string expr)
{
	bitset<N> ans;//最终的答案,若ans[i], 也即user[i]在返回的结果中

	if (expr[0] == '&' || expr[0] == '|') {//如果为逻辑表达式
		stack<char> s; s.push('(');
		int i = 1;
		while (!s.empty()) {  //仍然用栈的方法实现括号匹配
			i++;
			if (expr[i] == '(') s.push('(');
			else if (expr[i] == ')') s.pop();
		}
		//出循环时expr[i] == ),为第一个括号的最右端

		string expr1 = expr.substr(2, i - 2);
		string expr2 = expr.substr(i + 2, expr.size() - i - 3);

		bitset<N> res1 = handle(expr1);
		bitset<N> res2 = handle(expr2);

		if (expr[0] == '&') ans = res1 & res2;
		else ans = res1 | res2;
		return ans;
	}

	else {  //如果为基础表达式
		int i = 0;
		while (expr[i] != ':' && expr[i] != '~') i++;
		string key = expr.substr(0, i);
		string value = expr.substr(i + 1, expr.size() - i - 1);

		bool flag = false;  //该操作是否为反断言
		if (expr[i] == '~') flag = true;

		for (auto x : hash_kv[{key, value}]) {
			ans[x] = 1;   //x所对的位置应该是1,也即答案中存在该dn
		}

		if (flag) {  //如果为反断言
			for (auto x : hash_k[key]) {
				ans.flip(x);   //flip是取反操作
				//对于拥有该key的,目前只有value值匹配的ans位是为一的
				//现在进行取反操作,这会导致刚刚所取值1的,也就是value值匹配的,都修改为0
				//而其余具有该key的(但value值不相等的), 则会置为1.此时完成了我们的要求
			}
		}

	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n;
	for (int i = 1;i <= n;i++) {
		int dn; cin >> dn;
		user[i] = dn;
		int k; cin >> k;
		while (k--) {
			string key, val; cin >> key >> val;
			hash_k[key].insert(i);
			hash_kv[{key, val}].insert(i);
		}
	}

	int m; cin >> m;
	string line;

	while (m--) {
		cin >> line;
		bitset<N> v = handle(line);
		vector<int> ans;  //存储答案

		for (int i = 1;i <= n;i++) {
			if (v[i]) ans.push_back(user[i]);
		}
		sort(ans.begin(), ans.end());  //排序
		for (auto x : ans) cout << x << ' ';
		cout << endl;
	}
}

坑点:

可能会卡常

相关推荐

  1. Web3创作整理 - 2024-02-23 ~ 2024-03-25

    2024-03-29 21:06:02       43 阅读
  2. 2023.03.28

    2024-03-29 21:06:02       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-29 21:06:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-29 21:06:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-29 21:06:02       87 阅读
  4. Python语言-面向对象

    2024-03-29 21:06:02       96 阅读

热门阅读

  1. go中方法的Receiver (值类型&指针类型)

    2024-03-29 21:06:02       47 阅读
  2. 【JVM】双亲委派机制

    2024-03-29 21:06:02       41 阅读
  3. ConvE算法模型

    2024-03-29 21:06:02       34 阅读
  4. 跨时钟域学习记录(二)——XPM_CDC

    2024-03-29 21:06:02       32 阅读
  5. Tiktok 商务中心后台账户学习

    2024-03-29 21:06:02       39 阅读