邮件传输代理的交互(The Letter Carrier‘s Rounds, ACM/ICPC World Finals 1999, UVa814)rust解法

本题的任务为模拟发送邮件时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<string,vector<string>>,其中键是MTA名称,值是用户名列表。一个更简单的方法是用一个set<string>,值就是邮件地址。
对于每个请求,首先读入发件人,分离出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);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值