HDU - 2723 Electronic Document Security

本文介绍了一个文档权限管理系统的设计与实现,该系统使用访问控制列表(ACL)来管理文档的创建、查看、编辑和分发等各项操作。文章详细解析了如何通过ACL记录不同用户的权限变更,并最终计算出当前文档的有效权限分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Tyrell corporation uses a state-of-the-art electronic document system that controls all aspects of document creation, viewing, editing, and distribution. Document security is handled via access control lists (ACLs). An ACL defines a set of entities that have access to the document, and for each entity defines the set of rights that it has. Entities are denoted by uppercase letters; an entity might be a single individual or an entire division. Rights are denoted by lowercase letters; examples of rights are a for append, d for delete, e for edit, and r for read. 

The ACL for a document is stored along with that document, but there is also a separate ACL log stored on a separate log server. All documents start with an empty ACL, which grants no rights to anyone. Every time the ACL for a document is changed, a new entry is written to the log. An entry is of the form ExR, where E is a nonempty set of entities, R is a nonempty set of rights, and x is either "+", "–", or "=". Entry E+R says to grant all the rights in R to all the entities in E, entry E–R says to remove all the rights in R from all the entities in E, and entry E=R says that all the entities in E have exactly the rights in R and no others. An entry might be redundant in the sense that it grants an entity a right it already has and/or denies an entity a right that it doesn't have. A log is simply a list of entries separated by commas, ordered chronologically from oldest to most recent. Entries are cumulative, with newer entries taking precedence over older entries if there is a conflict. 

Periodically the Tyrell corporation will run a security check by using the logs to compute the current ACL for each document and then comparing it with the ACL actually stored with the document. A mismatch indicates a security breach. Your job is to write a program that, given an ACL log, computes the current ACL.
Input
The input consists of one or more ACL logs, each 3–79 characters long and on a line by itself, followed by a line containing only "#" that signals the end of the input. Logs will be in the format defined above and will not contain any whitespace.
Output
For each log, output a single line containing the log number (logs are numbered sequentially starting with one), then a colon, then the current ACL in the format shown below. Note that (1) spaces do not appear in the output; (2) entities are listed in alphabetical order; (3) the rights for an entity are listed in alphabetical order; (4) entities with no current rights are not listed (even if they appeared in a log entry), so it's possible that an ACL will be empty; and (5) if two or more consecutive entities have exactly the same rights, those rights are only output once, after the list of entities.
Sample Input
MC-p,SC+c
YB=rde,B-dq,AYM+e
GQ+tju,GH-ju,AQ-z,Q=t,QG-t
JBL=fwa,H+wf,LD-fz,BJ-a,P=aw
#
Sample Output
1:CSc
2:AeBerMeYder
3:
4:BHJfwLPaw
 
 
哇···  QAQ,写了两个小时的模拟,整个学校的智商都被我拉低了,一遇到模拟题就怂,没有任何算法可言,就是利用非常暴力的方法,真的是暴力暴力秒天秒地,最后一发过,估计是数据太水了吧。
题意如下:
额-_-,题意吧,就是ExR型的操作,E代表用户,R表示权限,x代表三种操作(即‘-’‘+’‘=’),- 表示将用户E的权限R去掉,+ 表示给用户E加上权限R,= 表示重新给用户E授权R(以前的权限清除),这里要记住每个逗号隔开是一组ExR型的输入,E和R输入都不唯一,有可能多个权限对多个用户操作,实践是检验真理的唯一标准,说那么多不如解释一下样例来的实际,就解释一下第四个样例吧:
样例四:JBL=fwa,H+wf,LD-fz,BJ-a,P=aw
JBL=fwa 表示将用户JBL的权限重置,然后把权限fwa授给JBL
H+wf    表示将用户H的权限再加上wf两种权限
LD-fz   表示取消用户L和D的fz两种权限
BJ-a    表示取消用户B和J的a权限
P=aw    表示将用户P的权限重置,然后把权限aw授给P
最后把拥有权限的用户按照字典序输出来,有一点,相邻的用户如果权限一样,那么将会写在一起,比如样例一:不是1:CcSc,而是1:CSc
 
 
思路嘛,就是模拟了,能看懂代码就看吧。。。
//HDU 2723
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxn 100005
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson step<<1
#define rson step<<1|1
#define MOD 1000000009
#define sqr(a) ((a)*(a))
using namespace std;
char s[1050];
int a[28][28];
int main() {
	int m;//长度 
	int count = 1;
	char E[105];//代表授给权限的人 E 
	char R[105];//代表所授的权限R 
	while(~scanf("%s",s) && s[0] != '#') {
		m = strlen(s);
		mem(a , 0);
		int i = 0;
		for(; i < m; i++) {               //一个比较繁琐的循环 
			if(i == 0 || s[i] == ',') {   //当i=0或者s[i]=','的时候开始一段新的ExR 
				int j = i , e = 0 , r = 0;//e 是E[]的下标, r 是R[]的下标 
				if(s[i] == ',') j++;      // 如果是逗号就开始新的授权,即j++ 
				for(; j < m; j++) {
					if(s[j] >= 'A' && s[j] <= 'Z')
					E[e++] = s[j];        //把授给权限的人记录下来 
					else break;
				}
				int t = -1;
				if(s[j] == '-') t = 0;      // 0:-  1:+   2:=
				else if(s[j] == '+') t = 1; // 此处用于记录操作是增加还是减少或者重置权限; 
				else t = 2;
				j++;                        //j++ 开始记录所授的权限 
				for(; j < m; j++) {
					if(s[j] >= 'a' && s[j] <= 'z') {
						R[r++] = s[j];
					}
					else break;
				}
				//以上把E存在了E[]里,把R存在了R[]里; 
				if(t == 0) {         //减少权限操作 
					for(int I = 0; I < r; I++) {
						for(int J = 0; J < e; J++) {
							a[R[I]-'a'+1][E[J]-'A'+1] = 0;  //把拥有权限的用户以及权限存在二维数组里 
						}
					}	
				}
				else if(t == 1) {    //增加权限操作 
					for(int I = 0; I < r; I++) {
						for(int J = 0; J < e; J++) {
							a[R[I]-'a'+1][E[J]-'A'+1] = 1;
						}
					}					
				}
				else if(t == 2){      //重置权限操作 
					for(int I = 0; I < 28; I++) {
						for(int J = 0; J < e; J++) {
							a[I][E[J]-'A'+1] = 0;
						}
					}
					for(int I = 0; I < r; I++) {
						for(int J = 0; J < e; J++) {
							a[R[I]-'a'+1][E[J]-'A'+1] = 1;
						}
					}
				}
			}
		}
		int t = 1;
		int AC[1005];
		for(int j = 0; j < 28; j++) {
			for(i = 0; i < 28; i++)
			if(a[i][j]) {
				AC[t++]  = j;     //将所有的用户给记录下来 
			}
		}
		printf("%d:",count++);
		t = unique(AC+1,AC+t)-AC;//用于把记录下来的用户去重 
		int temp;                //标记 
		for(int j = 1; j < t; j++) {
			if(AC[j]) {
				printf("%c",AC[j]-1+'A');
			}
			for(int k = j+1; k < t; k++) {
				temp = 1;
				for(int l = 1; l < 27; l++) {
					if(a[l][AC[j]] != a[l][AC[k]]) {  //进行匹配; 
						temp = 0;
						break;
					}
				}
				if(temp == 1 && AC[k]) {
					printf("%c",AC[k]-1+'A');
					AC[k]=0;
				}
				else break;
			}
			for(int k = 0; k < 28; k++) {
				if(a[k][AC[j]]) {
					printf("%c",k-1+'a');
				}
			}
		}
		printf("\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值