Fifnmar edited 4 年,10 月前
讨论区放不下,有点长了。但我得吐糟一下,为什么 OJ 会直接吞了我辛苦写的东西 Orz
刚看这道题的时候,我好奇为什么是道 Hard
难度的题。现在看应该是因为数据量吧。
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>
class Email {
std::string user_name;
std::string domain;
public:
Email(std::string const &raw_address) {
auto at_pos = raw_address.find('@');
assert(at_pos != std::string::npos);
user_name = raw_address.substr(0, at_pos);
domain = raw_address.substr(at_pos + 1);
}
bool operator<(Email const &rhs) const {
if (domain == rhs.domain) {
return user_name > rhs.user_name;
} else {
return domain < rhs.domain;
}
}
std::ostream &output_full_address(std::ostream &out) const {
return out << user_name << '@' << domain;
}
};
int main() {
using namespace std;
uint32_t n; cin >> n;
vector<Email> emails;
for (uint32_t i = 0; i < n; ++i) {
string temp; cin >> temp;
emails.push_back({temp});
}
sort(emails.begin(), emails.end());
for (auto const &i : emails) {
i.output_full_address(cout) << '\n';
}
}
有同学想看 C 语言的写法,我用同样的思想重写了一下。
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// I extract a struct of Dynamic string out here,
// making it a separate struct. Actually we can
// make an integrated struct `Email` and handle
// all the work inside, which will reduce the
// code length for this of our need.
// ********************************************* //
// Handle to a dynamic string;
typedef struct {
char *raw_str;
size_t size; // Always less than _reserve.
size_t _reserve;
} Dynstr;
// DOES NOT guarantee against EOF.
// Reads one more space and then discard it.
Dynstr read_dynstr(FILE *read_source) {
Dynstr ret;
ret.size = 0;
ret.raw_str = (char *)malloc(sizeof(char) * 16);
ret._reserve = 16;
int ch;
while (isspace(ch = getc(read_source))) {
assert(ch != EOF);
}
do {
ret.raw_str[ret.size++] = ch;
if (ret.size == ret._reserve) {
char *temp = (char *)malloc(sizeof(char) * (ret._reserve <<= 1));
memcpy(temp, ret.raw_str, ret.size);
free(ret.raw_str);
ret.raw_str = temp;
}
ch = getc(read_source);
} while (!isspace(ch));
ret.raw_str[ret.size] = '\0';
return ret;
}
typedef struct {
// I choose to use (ptr, size) instead of (begin, end),
// in respect of C conventions.
Dynstr const *_raw_address_view;
char *user_name_bg;
char *domain_bg;
size_t user_name_size;
size_t domain_size;
} hdlEmail; // handle to Email.
hdlEmail get_email_handle(Dynstr const *full_address) {
hdlEmail ret;
char *iter = full_address->raw_str;
for (; *iter != '@'; ++iter) {
assert((size_t)(iter - full_address->raw_str) < full_address->size);
}
ret._raw_address_view = full_address;
ret.user_name_bg = full_address->raw_str;
ret.user_name_size = iter - ret.user_name_bg;
ret.domain_bg = iter + 1;
ret.domain_size = full_address->size - ret.user_name_size - 1;
return ret;
}
// Unsafe: Breaks the `const` and temporarily changes the key strings.
int hdlEmail_cmp(void const *_lhs, void const *_rhs) {
*(((hdlEmail *)_lhs)->domain_bg - 1) = '\0';
int a = strcmp(((hdlEmail *)_lhs)->domain_bg, ((hdlEmail *)_rhs)->domain_bg);
if (a == 0)
a = strcmp(((hdlEmail *)_rhs)->user_name_bg, ((hdlEmail *)_lhs)->user_name_bg);
*(((hdlEmail *)_lhs)->domain_bg - 1) = '@';
return a;
}
int main() {
uint32_t n; scanf("%u", &n);
Dynstr *strarr = (Dynstr *)malloc(sizeof(Dynstr) * n);
hdlEmail *hdlarr = (hdlEmail *)malloc(sizeof(hdlEmail) * n);
for (uint32_t i = 0; i < n; ++i) {
strarr[i] = read_dynstr(stdin);
hdlarr[i] = get_email_handle(strarr + i);
}
qsort(hdlarr, n, sizeof(hdlEmail), hdlEmail_cmp);
for (uint32_t i = 0; i < n; ++i) {
printf("%s\n", hdlarr[i]._raw_address_view->raw_str);
}
free(strarr);
}
可以看出要手动撸一些东西。实际上如果不是在做题的话还是可以找到很多基础库,用起来应该也能行,没必要自己写。
效率上,我的 C 代码跟 C++ 代码不相上下,可能是因为思路基本是相同的叭。
// 这道题又是劝同学们放弃 C 语言的一个铁证(滑稽),珍爱生命,远离 C 语言。