本题的任务为模拟发送邮件时MTA(邮件传输代理)之间的交互。所谓MTA,就是
email地址格式user@mtaname的“后面部分”。当某人从user1@mta1发送给另一个人user2@mta2
时,这两个MTA将会通信。如果两个收件人属于同一个MTA,发送者的MTA只需与这个
MTA通信一次就可以把邮件发送给这两个人。
输入每个MTA里的用户列表,对于每个发送请求(输入发送者和接收者列表),按顺序
输出所有MTA之间的SMTP(简单邮件协议)交互。协议细节参见原题。
发送人MTA连接收件人MTA的顺序应该与在输入中第一次出现的顺序一致。例如,若发件人是Hamdy@Cairo,收件人列表为Conrado@MexicoCity、Shariff@SanFrancisco、
Lisa@MexicoCity,则Cairo应当依次连接MexicoCity和SanFrancisco。
如果连接某个MTA之后发现所有收件人都不存在,则不应该发送DATA。所有用户名均由不超过15个字母和数字组成。
【分析】
本题的关键是理清各个名词之间的逻辑关系以及把要做的事情分成几个步骤。首先是输入过程,把每个MTA里的用户列表保存下来。一种方法是用一个map
,其中键是MTA名称,值是用户名列表。一个更简单的方法是用一个set
,值就是邮件地址。
对于每个请求,首先读入发件人,分离出MTA和用户名,然后读入所有收件人,根据MTA出现的顺序进行保存,并且去掉重复。接下来读入邮件正文,最后按顺序依次连接每个MTA,检查并输出每个收件人是否存在,如果至少有一个存在,则输出邮件正文。
样例:
输入
MTA London 4 Fiona Paul Heather Nevil
MTA SanFrancisco 3 Mario Luigi Sheriff
MTA Paris 3 Jacque Suzanne Maurice
MTA HongKong 3 Chen Jeng Hee
MTA MexicoCity 4 Conrado Estella Eva Raul
MTA Cairo 3 Hamdy Tarik Misa
*
Hamdy@Cairo Conrado@MexicoCity Sheriff@SanFrancisco Lisa@MexicoCity
*
Congratulations on your efforts !!
—Hamdy
*
Fiona@London Chen@HongKong Natasha@Paris
*
Thanks for the report!
—Fiona
*
*
输出
connection between Cairo and MexicoCity
from Hamdy@Cairo
to Conrado@MexicoCity
not found Lisa@MexicoCity
data
Congratulations on your efforts !!
—Hamdy
connection between Cairo and SanFrancisco
from Hamdy@Cairo
to Sheriff@SanFrancisco
data
Congratulations on your efforts !!
—Hamdy
connection between London and HongKong
from Fiona@London
to Chen@HongKong
data
Thanks for the report!
—Fiona
connection between London and Paris
from Fiona@London
not found Natasha@Paris
解法:
use std::{
collections::{HashMap, HashSet},
io,
};
fn main() {
let mut users = HashSet::new();
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
buf = buf.trim().to_string();
if buf == "*" {
break;
}
let it = buf.split_whitespace();
let mut it = it.skip(1);
let mta = it.next().unwrap().to_string();
let _n: usize = it.next().unwrap().parse().unwrap();
for user in it {
users.insert(user.to_string() + "@" + &mta);
}
}
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
if buf.trim() == "*" {
break;
}
let mut it = buf.split_whitespace();
let sender = it.next().unwrap().to_string();
let mut mta_emails: HashMap<String, Vec<String>> = HashMap::new();
let mut recievermtas: Vec<String> = vec![];
let mut emails: HashSet<String> = HashSet::new();
for email in it {
if emails.contains(&email.to_string()) {//去重
continue;
}
emails.insert(email.to_string());
let idx = email.find('@').unwrap();
let mta = email[idx + 1..].to_string();
mta_emails
.entry(mta.clone())
.and_modify(|x| x.push(email.to_string()))
.or_insert(vec![email.to_string()]);
if recievermtas.contains(&mta) {
continue;
} else {
recievermtas.push(mta);
}
}
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
let mut data = String::new();
loop {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
if buf.trim() == "*" {
break;
}
data += &(" ".to_owned() + &buf);
}
for i in recievermtas.iter() {
let mut bdata = false;
let idx = sender.find('@').unwrap();
let sendermta = sender[idx + 1..].to_string();
println!("connection between {} and {}", sendermta, i);
println!(" from {}", sender);
for j in mta_emails.get(i).unwrap() {
if users.contains(j) {
println!(" to {}", j);
bdata = true;
} else {
println!(" not found {}", j);
}
}
if bdata {
println!(" data\n{}", data);
}
}
}
}