CCF yyds!
先放上一份debug数据,可以先看看这个试试,如果都没有问题就再看看题解吧
这是输入
1 2 3 4 5 6 7 8 9 10 11
| 5
Server 10.1.01.2:8080
Server 1.0.100000000000.1:8080
Server 1:0.0.0.0
Server 12..3.9:3
Server ??1.2.3.4:13
|
输出
如果还没看出问题,那就看看这份题解吧。
题目简介
- 给你 $n$ 个操作,每个操作为创建服务器或连接服务器,在服务器字符串合法下,按照连接情况给出输出:
OK
或 FAIL
,但如果不合法,输出 ERR
。
题目解决
这个题大体分为3个步骤:
输入
判断地址串是否合法(最重要)。
判断服务器和客户机,按照情况输出。
重点还是判断地址串是否合法
地址不得出现除题目规定外的奇奇怪怪字符。
地址必须要有 5 个数(比如 12..2.6:9
就不行,也就是出现连着的点)。
地址必须含有 3 个 “.” 与 1 个 “:”,且顺序不能颠倒。
地址的 5 个数要符合题目规定的数据范围。(可能会超出int大小)
地址的 5 个数不能含前导 0。
代码实现
1. 服务器地址判断还是有很多坑点的,详见代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| bool check(string str){ int cnt1=0,cnt2=0; int len=str.size(); for(int i=0;i<len;++i){ if(str[i]=='.') cnt1++; if(str[i]==':') cnt2++; if(cnt2==1&&cnt1<3)return 0; if((str[i]<'0'||str[i]>'9')&&(str[i]!='.')&&(str[i]!=':'))return 0; } if(cnt1!=3||cnt2!=1)return 0; long long int num[5]={-1,-1,-1,-1,-1}; int now=0; str[len]='.'; for(int i=0;i<len;i++){ if(num[now]==-1&&(str[i]<'0'||str[i]>'9')) return 0; else if(num[now]==-1&&(str[i]=='0'&&str[i+1]!='.'&&str[i+1]!=':')) return 0; else if(str[i]<'0'||str[i]>'9') ++now; else if(num[now]==-1) num[now]=(str[i]&15); else num[now]=(num[now]<<1)+(num[now]<<3)+(str[i]&15); if(num[now]>65535)return 0; } if(str[len-1]==':') return 0; if(num[0]<=255&&num[1]<=255&&num[2]<=255&&num[3]<=255&&num[4]<=65535) return 1; else return 0; }
|
2. 主函数的实现——map。
map 是有序键值对容器,它的元素的键是唯一的。搜索、移除和插入操作拥有对数复杂度。map 通常实现为红黑树。
你可能需要存储一些键值对,例如存储学生姓名对应的分数:Tom 0,Bob 100,Alan 100。但是由于数组下标只能为非负整数,所以无法用姓名作为下标来存储,这个时候最简单的办法就是使用 STL 中的map
了!
用法:可以直接通过下标访问来进行查询或插入操作。例如 mp [Alan] = 100。
选自OI wiki
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| int main(){ string lx,dz; int n; cin>>n; for(int i=1;i<=n;i++){ cin>>lx>>dz; if(lx[0]=='S'){ if(!check(dz)) cout<<"ERR"<<endl; else if(M[dz]) cout<<"FAIL"<<endl; else{ M[dz]=i; cout<<"OK"<<endl; } } else{ if(!check(dz)) cout<<"ERR"<<endl; else if(!M[dz]) cout<<"FAIL"<<endl; else cout<<M[dz]<<endl; } } return 0; }
|
最后放出ac代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include<map> #include<iostream> using namespace std; #define N #define ri register int bool check(string str){ int cnt1=0,cnt2=0; int len=str.size(); for(int i=0;i<len;++i){ if(str[i]=='.') cnt1++; if(str[i]==':') cnt2++; if(cnt2==1&&cnt1<3)return 0; if((str[i]<'0'||str[i]>'9')&&(str[i]!='.')&&(str[i]!=':'))return 0; } if(cnt1!=3||cnt2!=1)return 0; long long int num[5]={-1,-1,-1,-1,-1}; int now=0; str[len]='.'; for(int i=0;i<len;i++){ if(num[now]==-1&&(str[i]<'0'||str[i]>'9')) return 0; else if(num[now]==-1&&(str[i]=='0'&&str[i+1]!='.'&&str[i+1]!=':')) return 0; else if(str[i]<'0'||str[i]>'9') ++now; else if(num[now]==-1) num[now]=(str[i]&15); else num[now]=(num[now]<<1)+(num[now]<<3)+(str[i]&15); if(num[now]>65535)return 0; } if(str[len-1]==':') return 0; if(num[0]<=255&&num[1]<=255&&num[2]<=255&&num[3]<=255&&num[4]<=65535) return 1; else return 0; } map<string,int> M; int main(){ string lx,dz; int n; cin>>n; for(int i=1;i<=n;i++){ cin>>lx>>dz; if(lx[0]=='S'){ if(!check(dz)) cout<<"ERR"<<endl; else if(M[dz]) cout<<"FAIL"<<endl; else{ M[dz]=i; cout<<"OK"<<endl; } } else{ if(!check(dz)) cout<<"ERR"<<endl; else if(!M[dz]) cout<<"FAIL"<<endl; else cout<<M[dz]<<endl; } } return 0; }
|
再放上一份考场代码(大家就图一乐,看看就行,a不了),但可以看看思路,思路没问题,应该比ac代码好理解点。