【202206-3】角色授权

2023-10-27

AC的快乐无与伦比!
本蒟蒻刚看到这道题时,就被超长的题干和复杂的关系唬住了。
于是学习了各路大神的解法,终于AC 成功照虎画猫了!
现将在此过程中学到的种种知识总结如下,作为本小白菜(不但小白还有菜)的编程笔记。

Attention:

一、C++中的万能头文件

#include<bits/stdc++.h>

在学习许多大神的代码中,发现这个头文件被使用的频率很高。

它是C++中支持的一个几乎万能的头文件,几乎包含所有的可用到的C++库函数。以后写代码就可以直接引用这一个头文件了,不需要在写一大堆vector、string、map、stack……

最初我的vscode中写入这个头文件会提示错误,是因为本地没有该头文件的具体内容。观察发现这是一个stdc++.h,在bits的文件中,因此在头文件iostream所在的文件,创建新文件夹bits,在其中写入stdc++.h就可。

二、题目理解

因为本蒟蒻的记忆能力堪忧,只能通过非常直接的变量命名来告知自己其含义。
最初不明晰各个事物的联系,不知如何组织数据结构,后来找到一个解析是从输入进行入手进行组织分析,甚好。

因此,以下分析也从输入入手:
①输入角色数量roleNum、角色关联数量roleRelatedNum、待检查的操作数量opToCheckNum。
接下来将会根据数量分别循环依次输入对应信息。

②输入角色相关信息。
对于这个重要的中心角色,我们使用结构体来组织数据。

struct role
{
	string name;
	map<string, int>op, resKind, resName;
}role[501];

建立起操作名、资源种类名、资源名到01(是否存在)的映射。如果该角色存在string s的操作名,则有role[i].op[s] = 1存在。
那么为什么不将这三类的数量也存入结构体里呢?
最初我是也存的,但是发现之后也用处不大,还占地方,就直接用三个变量opNum、resKindNum、resNameNum直接即时for循环处理之后要读入的相应数据了。
这里还用到一个数据结构是

map<string, int>nameID;

即建立起角色名称到其序号ID的一个映射。

③输入角色关联相关信息。
用户和用户组没有很大区别,可不作区分,这里的重点是,对于每个新用户或用户组(g或u后的字符串),计入与其对应的角色ID(每组输入的第一个字符串)。

map<string, vector<int>>conNameID;

第一次见识了vector。

vector是向量类型,可以容纳许多类型的数据,因此也被称为容器

比如我想让新用户temp存入与其关联的角色id,就

conNameID[temp].push_back(id);

让人不禁感叹,真是简洁又漂亮。

④输入待检查的操作+检查。
使用string group[404]来存放每个操作对应的组。
对于每个要执行操作的用户,先查其在步骤③存的一些关联的角色,使用check检查是否在该角色与之关联的情况下,后续操作是否可行。

这里for循环中使用

conNameID[temp].size()

表示用户temp关联的角色数量。

如果失败,那就再看我们本次输入中给的用户组,对于某一用户组在步骤③存的一些关联角色,使用check检查是否在该角色与之关联的情况下,后续操作是否可行。
其中利用flag标识已确认操作可行,及时退出循环。

⑤check检查是否可行的函数
三层if判断,拿第一层举例:

if((role[id].op.count(o) && role[id].op[o])||( role[id].op.count("*") && role[id].op["*"]))

检查角色是否有待检查的o操作,或者有通配符*标记着任何操作都可行。
大佬的check函数写得真好真妙! 我能说count()这个函数还是第一次见吗

函数返回值是bool类型,之前我一直习惯用int类型的01表示对错。
在一次次地运行超时中,终于动脑子查为啥别人用bool!

bool型变量占用内存一个字节,int型变量占用四个字节。
由于bool型变量只分0或非0,即false(0x00)或者true(0x01)。
在需要逻辑判断时可以使用bool型,可以避免使用int导致运行超时。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;

struct role
{
	string name;
	map<string, int>op, resKind, resName;
}role[501];

map<string, int>nameID;
map<string, vector<int>>conNameID;

int roleNum, roleRelatedNum, opToCheckNum;
int resNameNum, opNum, resKindNum, id, conObNum;
int groupNum, flag = 0;
string temp;
string group[404], opName, resKind, resName;

bool check(int id,const string &o,const string &z,const string &m)
{
	if((role[id].op.count(o) && role[id].op[o])||( role[id].op.count("*") && role[id].op["*"]))
		if((role[id].resKind.count(z) && role[id].resKind[z]) ||(role[id].resKind.count("*") && role[id].resKind["*"]))
			if((role[id].resName.count(m) && role[id].resName[m] )|| role[id].resName.size() == 0)
				return true;
	return false;
}

int main()
{
	cin>>roleNum>>roleRelatedNum>>opToCheckNum;
	for(int i = 0; i < roleNum; ++i)
	{
		cin>>role[i].name>>opNum;
		nameID[role[i].name] = i;
		for(int j = 0; j < opNum; ++j)
		{
			cin>>temp;role[i].op[temp] = 1;
		}
		cin>>resKindNum;
		for(int j = 0; j < resKindNum; ++j)
		{
			cin>>temp;role[i].resKind[temp] = 1;
		}
		cin>>resNameNum;
		for(int j = 0; j < resNameNum; ++j)
		{
			cin>>temp;role[i].resName[temp] = 1;
		}
	}

	for(int i = 0; i < roleRelatedNum; ++i)
	{
		cin>>temp;
		id = nameID[temp];
		cin>>conObNum;
		for(int j = 0; j < conObNum; ++j)
		{
			cin>>temp;
			cin>>temp;
			conNameID[temp].push_back(id);
		}
	}

	for(int i = 0; i < opToCheckNum; ++i)
	{
		flag = 0;
		cin>>temp>>groupNum;
		for(int j = 0; j < groupNum; ++j)
			cin>>group[j];
		cin>>opName>>resKind>>resName;
		for(int j = 0; j < conNameID[temp].size(); ++j)
		{
			int id = conNameID[temp][j];
			if(check(id, opName, resKind, resName))
			{
				flag = 1;
				break;
			}
		}
		if(!flag)
		{
			for(int j = 0; j < groupNum; ++j)
			{
				for(int k = 0; k < conNameID[group[j]].size(); ++k)
				{
					int id = conNameID[group[j]][k];
					if(check(id, opName, resKind, resName))
					{
						flag = 1;
						break;
					}
				}
				if(flag)break;
			}
		}
		cout<<flag<<endl;
	}
	return 0;
}

经此一役,发现map是个好东西,原来是非常常用的数据结构,它在第二题与第三题中都起了不可或缺的关键作用。
此过程中,通过拜读他人的优秀代码而从中窥得的算法分析、数据结构组织、编程习惯等,本蒟蒻也深深感受到了巨大的差距,实在道阻且长。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【202206-3】角色授权 的相关文章

随机推荐

  • 解决centos7 中 使用mariadb 安装mysql不成功的问题

    按照openstack官网的步骤安装openstack Install and configure components Install the packages yum install mariadb mariadb server pyt
  • 无需第三者的交换

    a i a i a index a index a i a index a i a i a index 无需第三者的交换
  • IDEA的使用

    文章目录 2 IDEA的使用 2 1 工具栏 2 2 启动IDEA选择项目 2 3 IDEA重启 2 4 自动提示区分大小写 2 5 tomcat启动中文乱码 2 5 1 修改tomcat 2 5 2 修改IDEA 2 6 jsp改变需要重
  • Alibaba Java Coding Guidelines,Java开发规范IDEA插件

    阿里巴巴Java开发规约 让开发者更加方便 快速将代码规范起来 Alibaba Java Coding Guidelines 是阿里巴巴基于手册内容 研发的一套自动化的IDE检测插件 IDEA Eclipse 安装步骤如下 1 打开 IDE
  • 13.8 asyncio高并发爬虫

    asyncio爬虫 去重 入库 import asyncio import re import aiohttp import aiomysql from pyquery import PyQuery from aiohttp import
  • java Spring Boot生成图片二维码

    首先 我们要引入依赖 pom xml中插入
  • pycharm快捷方式

    Python IDE PyCharm的快捷键大全 1 编辑 Editing Ctrl Space 基本的代码完成 类 方法 属性 Ctrl Alt Space 快速导入任意类 Ctrl Shift Enter 语句完成 Ctrl P 参数信
  • 新计算机c盘太小,电脑C盘太小,F盘太大,怎么重新调整分区容量?

    先在F盘装个系统 重新登陆后再把鼠标右击F盘盘符 注意先看好盘的大小 因为登陆后原来的F盘就成C盘了 原来的C盘名字也会改变成别的 所以事先最好记到多大的是F盘 多大的是C盘 1 单击 开始 控制面板 管理工具 计算机管理 计算机管理 在窗
  • QT系列第9节 文件目录操作

    QT编程中 文件目录操作很常见 现在就将常用的文件目录操作做一个总结 1 文件操作 QFile支持文本文件和二进制文件的操作 主要接口如下 qint64 read char data qint64 maxSize QByteArray re
  • ajax提交datagrid,AJAX DataGrid

    xmlns http tempuri org gt
  • PyTorch RuntimeError: DataLoader worker (pid(s) 15804) exited unexpectedly

    创建于 2021 10 20 1 报错 RuntimeError DataLoader worker pid s 15804 exited unexpectedly 网络上给出了方案 如 cuda 虚拟环境的共享内存不足 增大内存 改成更小
  • 窗口变化相关消息 OnSize、OnSizing和OnGetMinMaxInfo

    最近用到窗口变化的一些东西 遇到几个相关的消息函数 简要分析 作为备忘 3个消息分别是 WM SIZE WM SIZING WM GETMINMAXINFO 分别对应相应的处理函数 OnSize OnSizing OnGetMinMaxIn
  • Redis 10 大性能优化策略

    来源 阿里开发者 ID ali tech 一 Redis为什么变慢了 1 Redis真的变慢了吗 对 Redis 进行基准性能测试 例如 我的机器配置比较低 当延迟为 2ms 时 我就认为 Redis 变慢了 但是如果你的硬件配置比较高 那
  • Metasploitable2靶机渗透

    Metasploitable2靶机渗透 Metasploitable2介绍 Metasploitable2 虚拟系统是一个特别制作的ubuntu操作系统 本身设计作为安全工具测试和演示常见漏洞攻击 版本2已经可以下载 并且比上一个版本包含更
  • 阿里云服务器安全组放行宝塔端口8888

    阿里云服务器安装宝塔面板需要在安全组中开放8888 888 80 443 20 21端口 安全组默认只开放22和3389端口 阿里云服务器网来详细说下阿里云服务器ECS安全组开放宝塔面板端口的方法教程 云服务器安全组开放宝塔端口 阿里云服务
  • SpringBoot + Apache Shrio 构建通用权限系统,提示SecurityUtils.getSubject().getPrincipal() 转换类型错误

    构建SimpleAuthenticationInfo 权限配置信息 new SimpleAuthenticationInfo user password getName 参数说明 user 用户信息 password 用户密码 realm
  • Unity-网络开发(三)

    大小端模式 什么是大小端模式 大端模式 是指数据的高字节保存在内存的低地址中 而数据的低字节保存在内存的高地址中 这样的存储模式有点儿类似于把数据当作字符串顺序处理 地址由小向大增加 数据从高位往低位放 符合人类的阅读习惯 小端模式 是指数
  • c语言桶排序对链表,关于算法:如果我们使用链表实现存储桶,存储桶排序的复杂度如何为O(n + k)?...

    我很好奇 如果我们使用通过链表实现的存储桶 为什么存储桶排序的运行时间为O n k 例如 假设我们有以下输入 n no of element 8 k range 3 array 2 2 1 1 1 3 1 3 桶将如下所示 1 1 gt 1
  • 虚拟化习题(1)

    1 单选题 vmdk后缀的文件是 A 磁盘文件 B 内存文件 C 快照文件 D 磁盘锁文件 2 单选题 链接克隆是通过父虚拟机的 创建而成 因此节省了磁盘空间 而且克隆速度非常快 但是克隆后的虚拟机性能能会有所下降 A 磁盘 B 镜像 C
  • 【202206-3】角色授权

    AC的快乐无与伦比 本蒟蒻刚看到这道题时 就被超长的题干和复杂的关系唬住了 于是学习了各路大神的解法 终于AC 成功照虎画猫了 现将在此过程中学到的种种知识总结如下 作为本小白菜 不但小白还有菜 的编程笔记 Attention 一 C 中的