算法竞赛入门经典 例题5-11

这篇博客介绍了一个C++程序,它模拟了简单邮件传输协议(SMTP),处理邮件发送给同一服务器上的多个接收者的情况。程序通过建立映射结构确保了有序性和避免重复,并在处理接收者时检查是否存在,确保邮件的正确传输。

UVa814

The Letter Carrier’s Rounds

模拟简易的简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)。

这道题中略微麻烦的地方在于处理发送至同一个服务器上多个接收者的邮件,既要保证有序,又要保证不重复,这可以通过建立一个map<string, vector<User>>类型的映射ToSend来实现,该映射为服务器名称到该服务器上的接收者的映射。当遍历接收者时,将该邮件也发送给同一服务器上的所有接收者,然后清空映射,这样就可以保证有序和不重复。

不用处理MTA不存在以及发送者不存在的情况。

#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#define INDENT "     "

using namespace std;

struct User
{
	string name;
	string mta;
	User(const string &address)
	{
		size_t AtPos = address.find('@');
		name.assign(address.substr(0, AtPos));
		mta.assign(address.substr(AtPos + 1));
	}
	User(const string &name, const string mta) : name(name), mta(mta) {};
	bool operator<(const User &user) const
	{
		return name + mta < user.name + user.mta;
	}
	string address() const
	{
		return name + '@' + mta;
	}
};

void SendMsg(const set<User> &ExistedUsers, const User &sender, const vector<User> &receivers, const vector<string> &MsgLines)
{
	map<string, vector<User>> ToSend;
	set<User> sent;
	for (const User &user : receivers)
	{
		if (sent.insert(user).second) {
			ToSend[user.mta].push_back(user);
		}
	}
	for (const User &user : receivers)
	{
		vector<User> &SameMTAUsers = ToSend.at(user.mta);
		if (SameMTAUsers.empty()) continue;
		bool NeedSend = false;
		cout << "Connection between " << sender.mta << " and " << user.mta << '\n';
		cout << INDENT"HELO " << sender.mta << '\n';
		cout << INDENT"250\n";
		cout << INDENT"MAIL FROM:<" << sender.address() << ">\n";
		cout << INDENT"250\n";
		for (const User &receiver : SameMTAUsers)
		{
			cout << INDENT"RCPT TO:<" << receiver.address() << ">\n";
			if (ExistedUsers.find(receiver) == ExistedUsers.end()) {
				cout << INDENT"550\n";
				continue;
			}
			else {
				NeedSend = true;
				cout << INDENT"250\n";
			}
		}
		if (NeedSend) {
			cout << INDENT"DATA\n";
			cout << INDENT"354\n";
			for (const string &line : MsgLines)
			{
				cout << INDENT << line << '\n';
			}
			cout << INDENT".\n";
			cout << INDENT"250\n";
		}
		cout << INDENT"QUIT\n";
		cout << INDENT"221\n";
		SameMTAUsers.clear();
	}
}

int main()
{
	string input;
	set<User> ExistedUsers;
	while (getline(cin, input)) {
		if (input == "*") break;
		stringstream ss(input.substr(4));
		string mta, name;
		int n;
		ss >> mta >> n;
		for (int i = 0; i < n; i++)
		{
			ss >> name;
			ExistedUsers.insert(User(name, mta));
		}
	}
	while (1) {
		cin >> input;
		if (input == "*") break;
		User sender(input);
		vector<User> receivers;
		while (cin >> input) {
			if (input == "*") break;
			receivers.push_back(User(input));
		}
		cin.get();
		vector<string> MsgLines;
		while (getline(cin, input)) {
			if (input == "*") break;
			MsgLines.push_back(input);
		}
		SendMsg(ExistedUsers, sender, receivers, MsgLines);
	}
	return 0;
}
/*
MTA London 4 Fiona Paul Heather Nevil
MTA SanFrancisco 3 Mario Luigi Shariff
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 Shariff@SanFrancisco Lisa@MexicoCity
*
Congratulations on your efforts !!
--Hamdy
*
Fiona@London Chen@HongKong Natasha@Paris
*
Thanks for the report! --Fiona
*
*
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值