<p>Every <strong>valid email</strong> consists of a <strong>local name</strong> and a <strong>domain name</strong>, separated by the <code>&#39;@&#39;</code> sign. Besides lowercase letters, the email may contain one or more <code>&#39;.&#39;</code> or <code>&#39;+&#39;</code>.</p>

<ul>
	<li>For example, in <code>&quot;alice@leetcode.com&quot;</code>, <code>&quot;alice&quot;</code> is the <strong>local name</strong>, and <code>&quot;leetcode.com&quot;</code> is the <strong>domain name</strong>.</li>
</ul>

<p>If you add periods <code>&#39;.&#39;</code> between some characters in the <strong>local name</strong> part of an email address, mail sent there will be forwarded to the same address without dots in the local name. Note that this rule <strong>does not apply</strong> to <strong>domain names</strong>.</p>

<ul>
	<li>For example, <code>&quot;alice.z@leetcode.com&quot;</code> and <code>&quot;alicez@leetcode.com&quot;</code> forward to the same email address.</li>
</ul>

<p>If you add a plus <code>&#39;+&#39;</code> in the <strong>local name</strong>, everything after the first plus sign <strong>will be ignored</strong>. This allows certain emails to be filtered. Note that this rule <strong>does not apply</strong> to <strong>domain names</strong>.</p>

<ul>
	<li>For example, <code>&quot;m.y+name@email.com&quot;</code> will be forwarded to <code>&quot;my@email.com&quot;</code>.</li>
</ul>

<p>It is possible to use both of these rules at the same time.</p>

<p>Given an array of strings <code>emails</code> where we send one email to each <code>emails[i]</code>, return <em>the number of different addresses that actually receive mails</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> emails = [&quot;test.email+alex@leetcode.com&quot;,&quot;test.e.mail+bob.cathy@leetcode.com&quot;,&quot;testemail+david@lee.tcode.com&quot;]
<strong>Output:</strong> 2
<strong>Explanation:</strong> &quot;testemail@leetcode.com&quot; and &quot;testemail@lee.tcode.com&quot; actually receive mails.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> emails = [&quot;a@leetcode.com&quot;,&quot;b@leetcode.com&quot;,&quot;c@leetcode.com&quot;]
<strong>Output:</strong> 3
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= emails.length &lt;= 100</code></li>
	<li><code>1 &lt;= emails[i].length &lt;= 100</code></li>
	<li><code>emails[i]</code> consist of lowercase English letters, <code>&#39;+&#39;</code>, <code>&#39;.&#39;</code> and <code>&#39;@&#39;</code>.</li>
	<li>Each <code>emails[i]</code> contains exactly one <code>&#39;@&#39;</code> character.</li>
	<li>All local and domain names are non-empty.</li>
	<li>Local names do not start with a <code>&#39;+&#39;</code> character.</li>
	<li>Domain names end with the <code>&quot;.com&quot;</code> suffix.</li>
</ul>

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;

inline namespace skyly {
    /* default c++ template for problem solving */
#ifdef LOCAL_DEBUG
    #include <dbg.h>
#else
    #define dbg(...) 77
#endif

    #define rep(i, n_rep) for (decay_t<decltype(n_rep)> i = 0; i < (n_rep); ++i)
    #define ffor(i, begin_i, end_i) for (decay_t<decltype(end_i)> i = (begin_i); i < (end_i); ++i)
    #define rfor(i, begin_i, end_i) for (decay_t<decltype(end_i)> i = (end_i) - 1; i >= (begin_i); --i)
    #define sz(x) int((x).size())
    #define all(x) begin(x), end(x)
    #define rall(x) rbegin(x), rend(x)
    #define each(x, lst) for (auto& x : lst)
    #define eachp(x, y, lst) for (auto& [x, y] : lst)

    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

    using I = int64_t;
    using U = uint64_t;
    using F = long double;
    using S = string;
    template <class T1, class T2> using P = pair<T1, T2>;
    template <class T> using V = vector<T>;
    template <class T, class Cmp = less<T>> using Set = tree<T, null_type, Cmp, rb_tree_tag, tree_order_statistics_node_update>;
    template <class T1, class T2, class Cmp = less<T1>> using Map = tree<T1, T2, Cmp, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class Cmp = less<T>> using pqueue = std::priority_queue<T, vector<T>, Cmp>;
    template<class T, class Cmp = less<T>> using Heap = __gnu_pbds::priority_queue<T, Cmp>;

    struct CustomHash {
        static U splitmix64(U x) {
            x += 0x9e3779b97f4a7c15;
            x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
            x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
            return x ^ (x >> 31);
        }
        size_t operator()(U x) const noexcept {
            static const U FIXED_RANDOM = rng();
            return splitmix64(x + FIXED_RANDOM);
        }
        template<typename T> size_t operator()(const P<T, T>& x) const {
            return (*this)(U(x.first)) ^ ((*this)(U(x.second)) >> 1);
        }
    };
    template <class T> using HashSet = gp_hash_table<T, null_type, CustomHash>;
    template <class T1, class T2> using HashMap = gp_hash_table<T1, T2, CustomHash>;

    template <typename T, T val = T(), typename... Args>
    auto make_vector(size_t x, Args... arr) {
        if constexpr (sizeof...(arr) == 0) return V<T>(x, val);
        else return vector(x, make_vector<T, val>(arr...));
    }

    inline namespace misc_defines {
        constexpr auto ssort = ranges::sort;
        template <typename T> using nlim = numeric_limits<T>;
        template <typename T, typename F = less<T>> void sort_unique(V<T>& v, F f = F()) { sort(all(v), f); v.resize(unique(all(v)) - begin(v)); }
        template <typename T> constexpr T sum(const V<T>& v) { return v.empty() ? T(0) : accumulate(v.cbegin(), v.cend(), T(0)); }
        template <typename T> constexpr bool chmax(T& a, const T& b) noexcept { return b > a ? a = b, true : false; }
        template <typename T> constexpr bool chmin(T& a, const T& b) noexcept { return b < a ? a = b, true : false; }
        template <typename T> constexpr T has_bit(T x, int i) noexcept { return x & (T(1) << i); }
        template <typename T> constexpr int log2_floor(T x) noexcept { static_assert(is_integral_v<T>);
            if (x <= T(0)) return -1;
            if constexpr (nlim<T>::digits <= nlim<unsigned int>::digits) return nlim<unsigned int>::digits - __builtin_clz(x) - 1;
            else return nlim<U>::digits - __builtin_clzll(x) - 1;
        }
        template <typename T> constexpr int log2_ceil(T x) noexcept { return log2_floor(x - 1) + 1; }
        constexpr F PI = numbers::pi_v<F>;
        constexpr int F_OUTPUT_PRECISION = 20;
    }
}
/* main part of the solution starts from here */

inline namespace solution_space {
/* begin */
bool to_init = true;

class Solution {
public:
    int numUniqueEmails(vector<string>& emails) {
        V<P<S, S>> arr;
        each (s, emails) {
            auto idx = s.find('@');
            auto s_domain = s.substr(idx + 1);
            auto s_local = s.substr(0, idx);
            if (idx = s.find('+'); idx != S::npos) s_local = s_local.substr(0, idx);
            S buf;
            each (ch, s_local) if (ch != '.') buf.push_back(ch);
            s_local = buf;
            arr.emplace_back(s_local, s_domain);
        }
        sort_unique(arr);
        return sz(arr);
    }
};
/*  end  */
}

#ifdef LOCAL_DEBUG
int main() {
    dbg("Ready to go...");
    Solution s;
    dbg("Program finished normally.");
    return 0;
}
#endif
21400