Robocom 真题 7-3 账户安全预警

7-3 账户安全预警

拼题 A 系统为提高用户账户的安全性,打算开发一个自动安全预警的功能。对每个账户的每次登录,系统会记录其登录的 IP 地址。每隔一段时间,系统将统计每个账户从多少不同的 IP 地址分别登录了多少次。如果某个账户的登录 IP 超过了 Tip 种,并且登录过于频繁,超过了 Tlogin次,则会自动向管理员发出警报。
下面就请你实现这个预警功能。

题目描述

输入首先在第一行中给出三个正整数:N(≤104)为登录记录的条数;TIPTlogin​,定义如题面中所描述,均不超过 100。

随后 N 行,每行格式为:

账户邮箱 IP地址

其中 账户邮箱 为长度不超过 40 的、不包含空格的非空字符串;IP地址 为形如 xxx.xxx.xxx.xxx 的合法 IP 地址。

输出格式

按照登录所用不同 IP 的数量的非递增顺序,输出每个预警账户的信息。格式为:

账户邮箱
IP1 登录次数
IP2 登录次数
……

其中 IP 按登录次数的非递增顺序输出,如有并列,则按 IP 的递增字典序输出。此外,对所用不同 IP 的数量并列的用户,按其账户邮箱的递增字典序输出。

另一方面,即使没有账户达到预警线,也输出登录所用不同 IP 的数量最多的一批账户的信息。

输入样例1

24 3 4
daohaole@qq.com 218.109.231.189
1jiadelaolao@163.com 112.192.203.187
chenyuelaolao@zju.edu.cn 112.18.235.143
jiadelaolao@163.com 112.192.203.187
chenyuelaolao@zju.edu.cn 113.18.235.143
jiadelaolao@163.com 111.192.203.187
daohaole@qq.com 218.109.231.189
chenyuelaolao@zju.edu.cn 111.18.235.143
1jiadelaolao@163.com 115.192.203.187
daohaole@qq.com 113.189.58.141
1jiadelaolao@163.com 111.192.203.187
daohaole@qq.com 112.18.58.145
1jiadelaolao@163.com 114.192.203.187
chenyuelaolao@zju.edu.cn 112.18.235.143
daohaole@qq.com 123.89.158.214
chenyuelaolao@zju.edu.cn 112.18.235.143
youdaohaole@qq.com 218.109.231.189
jiadelaolao@163.com 113.192.203.187
youdaohaole@qq.com 218.109.231.189
jiadelaolao@163.com 114.192.203.187
youdaohaole@qq.com 113.189.58.141
youdaohaole@qq.com 123.89.158.214
1jiadelaolao@163.com 113.192.203.187
youdaohaole@qq.com 112.18.58.145

输出样例1

1jiadelaolao@163.com
111.192.203.187 1
112.192.203.187 1
113.192.203.187 1
114.192.203.187 1
115.192.203.187 1
daohaole@qq.com
218.109.231.189 2
112.18.58.145 1
113.189.58.141 1
123.89.158.214 1
youdaohaole@qq.com
218.109.231.189 2
112.18.58.145 1
113.189.58.141 1
123.89.158.214 1

输入样例2

24 5 8
daohaole@qq.com 218.109.231.189
1jiadelaolao@163.com 112.192.203.187
chenyuelaolao@zju.edu.cn 112.18.235.143
jiadelaolao@163.com 112.192.203.187
chenyuelaolao@zju.edu.cn 113.18.235.143
jiadelaolao@163.com 111.192.203.187
daohaole@qq.com 218.109.231.189
chenyuelaolao@zju.edu.cn 111.18.235.143
1jiadelaolao@163.com 115.192.203.187
daohaole@qq.com 113.189.58.141
1jiadelaolao@163.com 111.192.203.187
daohaole@qq.com 112.18.58.145
1jiadelaolao@163.com 114.192.203.187
chenyuelaolao@zju.edu.cn 112.18.235.143
daohaole@qq.com 123.89.158.214
chenyuelaolao@zju.edu.cn 112.18.235.143
youdaohaole@qq.com 218.109.231.189
jiadelaolao@163.com 113.192.203.187
youdaohaole@qq.com 218.109.231.189
jiadelaolao@163.com 114.192.203.187
youdaohaole@qq.com 113.189.58.141
youdaohaole@qq.com 123.89.158.214
1jiadelaolao@163.com 113.192.203.187
youdaohaole@qq.com 112.18.58.145

输出样例2

1jiadelaolao@163.com
111.192.203.187 1
112.192.203.187 1
113.192.203.187 1
114.192.203.187 1
115.192.203.187 1

题解

        分析题目可得,我们需要找到邮箱访问的ip种数超过Tip种,并且邮箱总共访问的次数超过了Tlogin次的账户,并打印输出。注意,输出格式非常的有讲究,邮箱先按ip种类数排序(降序),(若ip种数相同)再按字典序(递增)输出,每个邮箱的ip地址按访问次数降序排序,(若访问次数相同)再按字典序增序输出。如果没有需要发出预警账户,那么,输出访问ip种数最大的邮箱(注意!!!可能不止一个!!)。

为了方便排序,我们设计两个结构体如下:

struct IP{
    string ip;      //ip名字
    int time;       //ip访问次数
};//该结构体为IP结构体
​
struct Email{
    string email;   //Email的名字
    int num;        //ip种数
};//该结构体为Email结构体 

排序(仿函数):

bool cmp(IP a,IP b){
    return a.time!=b.time?a.time > b.time : a.ip<b.ip;  
}
​
bool cmp2(Email a,Email b){
    return a.num!=b.num?a.num > b.num : a.email<b.email;    
}

输入:

int n,ip,login;//总访问次数,Tip,Tlogin
cin >> n >> ip >> login;
​
map<string,set<string> > ipx;   //记录原本的所有信息(邮箱名称,set<IP名称>)
map<pair<string,string>,int> loginx;    //记录对应邮箱中的某个IP访问次数({邮箱名,ip名},访问次数)
map<string,int> ttt;    //记录对应邮箱的总访问数
int max = 0;    //邮箱中的最大不同ip种数
​
for(int i = 0;i < n ;i++) {
        string a,b;
        cin >> a >> b;
        ipx[a].insert(b);
        ttt[a]++;
        loginx[{a,b}] += 1;
        if(max < ipx[a].size()){
            max = ipx[a].size();
        }
    }

装入结构体、排序:

map<string,set<string> >::iterator itxxx;
vector<Email> ben;  //用vector记录所有输入的邮箱
for(itxxx = ipx.begin();itxxx!=ipx.end();itxxx++){
    Email y;
    y.email = itxxx->first;
    y.num   = ipx[itxxx->first].size();
    ben.push_back(y);
}
sort(ben.begin(),ben.end(),cmp2);

筛选:

vector<Email> result;   //记录需要发预警的邮箱名字
for(int i = 0;i < ben.size();i++){
    if(ipx[ben[i].email].size() > ip && ttt[ben[i].email] > login)
        result.push_back(ben[i]);
}

当没有需要发出预警的邮箱时:

if(result.size() == 0) {
    for(int i = 0;i<ben.size();i++){
        if(ipx[ben[i].email].size() == max){    //判断一下是否是ip种数最大
            result.push_back(ben[i]);   //直接加入结果集
        }
    }
}

当有需要发出预警时:

for(int i = 0;i < result.size();i++) {      //将结果集输出
    cout << result[i].email << endl;
    set<string>::iterator itx;
    vector<IP> sortt;   //将邮箱中的ip放入容器中排序
    for(itx = ipx[result[i].email].begin();itx!=ipx[result[i].email].end();itx++){
        IP x;
        x.ip=*itx;
        x.time = loginx[{result[i].email,*itx}];
        sortt.push_back(x);
    }
    sort(sortt.begin(),sortt.end(),cmp);
    
    for(int i = 0;i < sortt.size();i++) {
        cout << sortt[i].ip << " " << sortt[i].time <<endl; 
    }
}

本题完成

技术点

熟练掌握STL中的容器特性和使用。模拟。

1.vector

动态数组。本题知识点如下:

vector.push_back();
vector.size();
//遍历可以直接使用下标访问

2.set

集合,不可重复出现。

set.insert();
set.begin();
set.end();
//遍历使用迭代器

3.map

映射。

//遍历使用迭代器
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值