题目描述:

TCP/IP 协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。

在本问题中,计算机分为两大类:服务机(Server)和客户机(Client)。服务机负责建立连接,客户机负责加入连接。

需要进行网络连接的计算机共有 n 台,编号为 1∼n,这些机器将按编号递增的顺序,依次发起一条建立连接或加入连接的操作。

每台机器在尝试建立或加入连接时需要提供一个地址串。服务机提供的地址串表示它尝试建立连接的地址,客户机提供的地址串表示它尝试加入连接的地址。

一个符合规范的地址串应当具有以下特征:

  1. 必须形如 a.b.c.d:e 的格式,其中 a, b, c, d, e 均为非负整数;
  2. 0≤a,b,c,d≤255,0≤e≤65535;
  3. a, b, c, d, e均不能含有多余的前导 0。

相应地,不符合规范的地址串可能具有以下特征:

  1. 不是形如 a.b.c.d:e 格式的字符串,例如含有多于 3 个字符 . 或多于 1 个字符 : 等情况;
  2. 整数 a, b, c, d, e 中某一个或多个超出上述范围;
  3. 整数 a, b, c, d, e 中某一个或多个含有多余的前导 0。

例如,地址串 192.168.0.255:80 是符合规范的,但 192.168.0.999:80192.168.00.1:10192.168.0.1:088192:168:0:1.233 均是不符合规范的。

如果服务机或客户机在发起操作时提供的地址串不符合规范,这条操作将被直接忽略。

在本问题中,我们假定凡是符合上述规范的地址串均可参与正常的连接,你无需考虑每个地址串的实际意义。

由于网络阻塞等原因,不允许两台服务机使用相同的地址串,如果此类现象发生,后一台尝试建立连接的服务机将会无法成功建立连接;除此之外,凡是提供符合规范的地址串的服务机均可成功建立连接。

如果某台提供符合规范的地址的客户机在尝试加入连接时,与先前某台已经成功建立连接的服务机提供的地址串相同,这台客户机就可以成功加入连接,并称其连接到这台服务机;如果找不到这样的服务机,则认为这台客户机无法成功加入连接。

请注意,尽管不允许两台不同的服务机使用相同的地址串,但多台客户机使用同样的地址串,以及同一台服务机同时被多台客户机连接的情况是被允许的。

你的任务很简单:在给出每台计算机的类型以及地址串之后,判断这台计算机的连接情况。

输入格式:

第一行,一个正整数 n。

接下来 n 行,每行两个字符串op,ad,按照编号从小到大给出每台计算机的类型及地址串。

其中op 保证为字符串 Server 或 Client 之一,ad 为一个长度不超过 25 的,仅由数字、字符 . 和字符 : 组成的非空字符串。

每行的两个字符串之间用恰好一个空格分隔开,每行的末尾没有多余的空格。

输出格式:

输出共 n 行,每行一个正整数或字符串表示第 i 台计算机的连接状态。其中:

如果第 i 台计算机为服务机,则:

  1. 如果其提供符合规范的地址串且成功建立连接,输出字符串 OK
  2. 如果其提供符合规范的地址串,但由于先前有相同地址串的服务机而无法成功建立连接,输出字符串 FAIL
  3. 如果其提供的地址串不是符合规范的地址串,输出字符串 ERR

如果第 ii 台计算机为客户机,则:

  1. 如果其提供符合规范的地址串且成功加入连接,输出一个正整数表示这台客户机连接到的服务机的编号。
  2. 如果其提供符合规范的地址串,但无法成功加入连接时,输出字符串 FAIL
  3. 如果其提供的地址串不是符合规范的地址串,输出字符串 ERR

输入输出样例:

输入 #1:

5
Server 192.168.1.1:8080
Server 192.168.1.1:8080
Client 192.168.1.1:8080
Client 192.168.1.1:80
Client 192.168.1.1:99999

输出 #1:

OK
FAIL
1
FAIL
ERR

输入 #2:

10
Server 192.168.1.1:80
Client 192.168.1.1:80
Client 192.168.1.1:8080
Server 192.168.1.1:80
Server 192.168.1.1:8080
Server 192.168.1.999:0
Client 192.168.1.1.8080
Client 192.168.1.1:8080
Client 192.168.1.1:80
Client 192.168.1.999:0

输出 #2:

OK
1
FAIL
FAIL
OK
ERR
ERR
5
1
ERR

输入 #3:

见附件中的 network/network3.in。

输出 #3:

见附件中的 network/network3.ans。

输入 #4:

见附件中的 network/network4.in。

输出 #4:

见附件中的 network/network4.ans。

说明/提示

【样例解释 #1】

计算机 1 为服务机,提供符合规范的地址串 192.168.1.1:8080,成功建立连接;

计算机 2 为服务机,提供与计算机 1 相同的地址串,未能成功建立连接;

计算机 3 为客户机,提供符合规范的地址串 192.168.1.1:8080,成功加入连接,并连接到服务机 1;

计算机 4 为客户机,提供符合规范的地址串 192.168.1.1:80,找不到服务机与其连接;

计算机 5 为客户机,提供的地址串 192.168.1.1:99999 不符合规范。

【数据范围】

测试点编号 n≤ 特殊性质
1 10 性质 1 2 3
2∼3 100 性质 1 2 3
54∼5 1000 性质 1 2 3
6∼8 1000 性质 1 2
9∼11 1000 性质 1
12∼13 1000 性质 2
14∼15 1000 性质 4
16∼17 1000 性质 5
18∼20 1000 无特殊性质

“性质 1”为:保证所有的地址串均符合规范;
“性质 2”为:保证对于任意两台不同的计算机,如果它们同为服务机或者同为客户机,则它们提供的地址串一定不同;
“性质 3”为:保证任意一台服务机的编号都小于所有的客户机;
“性质 4”为:保证所有的地址串均形如 a.b.c.d:e 的格式,其中 a, b, c, d, ea,b,c,d,e 均为不超过 10^9且不含有多余前导 0 的非负整数;
“性质 5”为:保证所有的地址串均形如 a.b.c.d:e 的格式,其中 a, b, c, d, e 均为只含有数字的非空字符串。

对于 100% 的数据,保证 1≤n≤1000。

附件下载:

network.ziphttps://www.luogu.com.cn/fe/api/problem/downloadAttachment/ezhbqmn8

思路:

看到需要由地址串映射到计算机编号,我们可以考虑使用STL库里面的 map。这里推荐使用用法基本相似但查询、修改复杂度均为 O(1)的 unordered_map(需要用到 C++11,若在本地无法编译则要加上编译选项)。

  • 先判断每台计算机提供的地址串是否符合规范,若不符合,直接输出 ERR
  • 对于每台服务器Server)提供的地址串,先在 unordered_map 中寻找该地址串是否已经建立映射(即是否已经有服务器提供相同地址串以建立连接),若已有则输出 FAIL,否则建立映射并输出 OK
  • 对于每台客户机 (Client)提供的地址串,先在unordered_map 中寻找该地址串是否已经建立映射(即是否已经有服务器提供该地址串以建立连接),若已有则该客户机可以加入连接,此时输出建立连接的服务器的编号,否则该客户机不能加入连接,输出 FAIL

这里先简单介绍一下 unordered_map 。
unordered_map 本质上就像一个数组,
只不过你可以自己定义键和值 (其实就是下标与它所对应的元素) 类型。

unordered_map<string,int> mp;  

这样你就有了一个可以用 string 类型映射到 int 类型的 unordered_map 数组 mp 。

mp["hello"] = 532;

这意味着在 mpmp 数组里,"hello" 对应着532 。

mp.count("hello");
mp.count("world");

判断该元素之前是否存在映射。 返回值分别为 1 和 0。
map 的用法则与其相似,这里不再赘述。

判断地址串是否存在的部分可以用 unordered_map 解决,那么整道题的重点则落在了如何判断地址串是否规范上。

我们先列出地址串不符合规范的所有可能形式。

  • 形如 a.b.c.d:e,其中整数 a,b,c,d,e 有一个数超过题目给定的范围(即 0≤a,b,c,d≤255 , 0≤e≤65535),或有一个数含有前导 0。
    针对这种情况,我们可以用如下的方法依次提取 a,b,c,d,e,并判断其是否在规定范围内。
bool check(string s)
{int len = s.length();long long tmp = 0;for(int i=0;i<len;i++){if(s[i]=='.'||s[i]==':'){if(0<=tmp&&tmp<=255)    //判断a,b,c,d是否符合规范{tmp = 0;      //清零continue;}else return false;}else if(s[i]<'0'||s[i]>'9') return false;if(i&&!tmp&&s[i-1]=='0') return false;   //这一行用来判断前导0tmp = tmp*10+s[i]-'0';   //读取数字}if(0<=tmp&&tmp<=65535) return true;    //判断e是否符合规范else return false;
}
  • 形如 a.b.c:d.e,其中字符 .或 :出现的顺序不规范。
    针对这种情况,我们可以用计数器分别记录 . 和 : 出现的次数,判断 : 出现时,.出现的次数是否为 3。
int cnt1=0,cnt2=0,cnt3=0;
for(int i=0;i<len;i++)
{if(s[i]=='.'||s[i]==':'){if(s[i]=='.') cnt1++;else if(s[i]==':') cnt2++;if(cnt1<3&&cnt2) return false;   //出现顺序是否规范/*判断a,b,c,d的范围是否规范*/}else if(s[i]<'0'||s[i]>'9') return false;/*判断前导0 以及提取数字*/
}
  • 形如 a..b.c:e 或 a.b.c:.e,其中字符 . 或 : 连着出现。

    这时候符号的数量符合规范,但数字的数量不符合规范。可以仿照情况2,用计数器记录数字出现的次数,并在最后判断字符和数字出现的次数是否符合规范。

  • 形如 .a.b.c:e 或 a.b.c.d:,其中字符 . 或 : 出现在地址串头尾。 针对字符出现在头的情况,我们可以在字符出现时判断是否已有数字出现;针对字符出现在尾的情况,可以用情况3的方法来解决。

这两种情况都需要加上数字的计数器。

int len = s.length();
long long tmp = 0;
int cnt1=0,cnt2=0,cnt3=0;
for(int i=0;i<len;i++)
{if((i==0||(s[i-1]=='.'||s[i-1]==':'))&&s[i]>='0'&&s[i]<='9') cnt3++;   //如果当前为第一个位置或前一个为字符,并且这个位置为数字if(s[i]=='.'||s[i]==':'){/*统计字符出现的次数*/if(cnt1<3&&cnt2) return false;    //出现顺序是否规范if(!cnt3) return false;   //如果字符在第一个数字前出现/*判断a,b,c,d的范围是否规范*/}else if(s[i]<'0'||s[i]>'9') return false;/*判断前导0 以及提取数字*/
}
if(cnt1!=3||cnt2!=1||cnt3!=5) return false;    //判断字符、数字出现的数量
/*判断e的范围是否规范
*/

将上述4种情况的解决方案拼在一起,就得到判断地址串是否规范的函数。

完整代码:

#include <bits/stdc++.h>
using namespace std;
int n;
unordered_map<string,int>address;
bool check(string s)
{int len = s.length();long long tmp = 0;int cnt1=0,cnt2=0,cnt3=0;for(int i=0;i<len;i++){if((i==0||(s[i-1]=='.'||s[i-1]==':'))&&s[i]>='0'&&s[i]<='9') cnt3++;//如果当前为第一个位置或前一个为字符,并且这个位置为数字if(s[i]=='.'||s[i]==':'){if(s[i]=='.') cnt1++;else if(s[i]==':') cnt2++;//统计字符出现的次数if(cnt1<3&&cnt2) return false;    //出现顺序是否规范if(!cnt3) return false;  //如果字符在第一个数字前出现if(0<=tmp&&tmp<=255)  //判断a,b,c,d的范围是否规范{tmp = 0;continue;}else return false;}else if(s[i]<'0'||s[i]>'9') return false;   //出现了奇怪的字符if(i&&!tmp&&s[i-1]=='0') return false;    //判断前导 0tmp = tmp*10+s[i]-'0';    //提取数字}if(cnt1!=3||cnt2!=1||cnt3!=5) return false;   //字符和数字出现的数量是否正确if(0<=tmp&&tmp<=65535) return true;   //判断e的范围else return false;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){string cpt,adr;cin>>cpt>>adr;if(!check(adr)) puts("ERR");   //如果地址串不符合规范else if(cpt=="Server"){if(address.count(adr)) puts("FAIL");else {address[adr] = i;puts("OK");}}else if(cpt=="Client"){if(address.count(adr)) printf("%d\n",address[adr]);else puts("FAIL");}}return 0;
}

总结:

这道题其实并不算很难,可以不用map直接手写结构也可以做出来,考的是对于字符串的应用。

题目链接:

[CSP-J 2021] 网络连接 - 洛谷https://www.luogu.com.cn/problem/P7911

[CSP-J 2021] 网络连接相关推荐

  1. CSP-J 2021 网络连接

    题面 本题有两个考点 1:判断地址串是否合法 没有什么技巧,按照说明一条条判断即可,大样例3几乎包含了所以情况了 调出来基本就过了 2:判断服务器是否存在及编号 可以直接用字符串哈希,或者直接用 ma ...

  2. VMware虚拟机的基础操作 网络连接模式 VMTools共享文件夹 2021.2kali_linux

    使用kali linux 2021.2 网络连接的三种模式 桥接模式 产生同一网段的IP,缺点是容易产生IP冲突 主机:192.168.0.30 虚拟:192.168.0.35 设想如果一个教室有15 ...

  3. SIGMOD 2021 论文简析:当公交网络连接满足通勤需求时的公共交通规划 Public Transport Planning

    SIGMOD-2021 论文简析:当公交网络连接满足通勤需求时的公共交通规划 - Public Transport Planning: When Transit Network Connectivit ...

  4. CSP-J 2021_3_网络连接

    时光飞逝,日月如梭,转眼间便到了11月,这也就意味着csp2021结束了... 我呢,也是在拼命的学习,我已经不再是那个水贴的我了(其实依旧是在水帖)         接下来我会陆续为大家送上2021 ...

  5. Linux的归档及压缩,Linux的cron时间计划任务, NTP网络时间协议 , 查看网络连接...

    linux的归档及压缩:                   1.节约空间                   2.方便对零散文档的管理     tar集成备份工具:         -c:    创 ...

  6. 人脑动态功能网络连接模式能够鉴别个体并预测其认知功能

    来源:神经科技 概要:近二十年来,基于静息态功能磁共振影像的人脑连接组学快速发展,为无创研究活体人脑的功能组织规律和网络运作机制提供了重要手段,大大促进了研究者对脑认知.脑发育和脑疾病神经机制的理解. ...

  7. 查看此docker网络连接模式_Docker:网络模式详解

    袖珍指南 Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创 ...

  8. 没信号也不怕?iPhone 14或将支持卫星网络连接呼救

    今日一大早,网上冲浪的小编刷到#iPhone14或将支持卫星网络连接#的话题冲上热搜,引发了网友们的广泛关注.据外媒报道,苹果计划在未来在Apple Watch中引入连接卫星功能,用户可以直接通过手表 ...

  9. linux查看网络连接命令,系统运维|使用netstat检测及监测网络连接

    大家好,我是邪恶君子!今天,邪恶就给大家分享一下,使用小小的一个netstat命令,就能让你检测出系统是否处于安全状态!!! 这篇文档,复杂°:简单:难易°:易.坚决让小白都看得懂,学得会,掌握牢,上 ...

最新文章

  1. ccna考试真题及经验介绍
  2. php mysql增删改查实例_php连接数据库实现用户数据的增删改查实例
  3. openssh for windows
  4. 抖音数据统计_通过对抖音用户的大数据分析,我总结了一些经验
  5. 学习笔记(11月03日)
  6. 网易云 6 亿用户音乐推荐算法
  7. 设计模式 原型模式_创新设计模式:原型模式
  8. 深浅克隆面试题汇总——附详细答案
  9. AD Framework 单点登录
  10. 解锁秋天\秋季借势的海波设计密码!
  11. 排序算法第二篇——折半插入排序
  12. 微信提示点击右上角浏览器中打开
  13. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
  14. 策略路由 本地策略+接口策略
  15. Chapter2 ROS通信机制----基础篇(Ⅰ)vs配置及通信基础
  16. HTML语句判断IE浏览器版本
  17. excel表格横向纵向变换_什么是报表工具?和 EXCEL 有什么区别?
  18. python--第四章 python流程控制语句
  19. 面向智慧教室物联网关键技术的研究与运用(待完成)
  20. Python爬虫HTTP异常:rllib.error.HTTPError: HTTP Error 418,伪装User-Agent以及fake-useragent插件的妙用

热门文章

  1. 【Python数据科学手册】Pandas——十二、处理时间序列
  2. UE5 Lumen实现分析
  3. 深度学习word2vec笔记之算法篇
  4. 2021百度网盘网页版视频在线倍速播放
  5. 运行JavaWeb项目报错Access denied for user ‘root‘@‘localhost‘ (using password: YES)
  6. 家用宽带优化-光猫桥接,路由器拨号
  7. 编译原理实验二 自上而下的语法分析器(算术表达式)
  8. 颜色空间内容讲解与图像分割应用
  9. 搭建文字转语音(TTS)服务器
  10. Android设计模式(十六)-中介者模式