## 1. Abridged Problem Statement

Given N email addresses, determine for each whether it is valid according to these rules:

- An address has the form `<prefix>@<suffix>`.
- `<prefix>` is one or more "words" separated by single dots. A "word" is one or more characters drawn from letters (a-z, A-Z), digits (0-9), underscore (_) or hyphen (-). Dots may not appear at the start or end of `<prefix>`, nor consecutively.
- `<suffix>` has the form `<prefix>.<domain>`, where `<prefix>` follows the same rules as above, and `<domain>` is exactly 2 or 3 letters (a-z, A-Z).

Output "YES" or "NO" for each address.



## 2. Detailed Editorial

### Overview

We need a straightforward parser that splits each candidate string into three parts: left-of-`@` (call it A), right-of-`@` but up to the last dot (call it B), and after that last dot (call it D). Then check:

  a) There is an `@` character.
  b) A is a valid prefix.
  c) B is a valid prefix.
  d) D is a valid domain of length 2 or 3 and composed only of letters.

Note that requiring A and B to be valid prefixes already forbids any second `@`, since `@` is not an allowed prefix symbol: if a stray `@` appears in the suffix, the prefix check on B fails.

### Checking a prefix (A or B)

- It must not be empty.
- It must not start or end with a dot.
- It must not contain two consecutive dots ("..").
- Every character must be either a dot or a "symbol".
- A "symbol" is: letter (isalpha), digit (isdigit), underscore `_`, or hyphen `-`.

### Checking a domain (D)

- Its length must be exactly 2 or 3.
- All characters must be letters (isalpha).

### Algorithm

For each email string S:

1. Find the position of the `@`. If none, it is invalid.
2. Let A = S[0..pos-1], suffixFull = S[pos+1..end].
3. In suffixFull, find the last dot. If none, invalid.
4. Let B = suffixFull[0..dotpos-1], D = suffixFull[dotpos+1..end].
5. Validate A and B with the prefix rules; validate D with the domain rules.
6. Print "YES" if all checks pass, otherwise "NO".

### Complexity

Each email is processed in O(L) time where L <= 100. With N <= 100, total work is O(10^4), easily within time limits.



## 3. C++ Solution

```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

int n;
vector<string> emails;

bool is_symbol(char ch) {
    return isalpha(ch) || isdigit(ch) || ch == '_' || ch == '-';
}

bool is_valid_prefix(const string& prefix) {
    if(prefix.empty() || prefix.front() == '.' || prefix.back() == '.') {
        return false;
    }
    bool last_char_was_dot = false;
    for(char ch: prefix) {
        if(ch == '.') {
            if(last_char_was_dot) {
                return false;
            }
            last_char_was_dot = true;
        } else if(!is_symbol(ch)) {
            return false;
        } else {
            last_char_was_dot = false;
        }
    }
    return true;
}

bool is_valid_domain(const string& domain) {
    if(domain.size() != 2 && domain.size() != 3) {
        return false;
    }
    for(char ch: domain) {
        if(!isalpha(ch)) {
            return false;
        }
    }
    return true;
}

bool is_valid_suffix(const string& suffix) {
    size_t pos = suffix.rfind('.');
    if(pos == string::npos) {
        return false;
    }
    string prefix = suffix.substr(0, pos);
    string domain = suffix.substr(pos + 1);
    return is_valid_prefix(prefix) && is_valid_domain(domain);
}

bool is_valid_email(const string& email) {
    size_t pos = email.find('@');
    if(pos == string::npos) {
        return false;
    }
    string prefix = email.substr(0, pos);
    string suffix = email.substr(pos + 1);
    return is_valid_prefix(prefix) && is_valid_suffix(suffix);
}

void read() {
    cin >> n;
    cin.ignore();
    emails.resize(n);
    for(auto& email: emails) {
        getline(cin, email);
    }
}

void solve() {
    // Validate each email against the grammar by splitting on punctuation:
    //
    // - An address is <prefix>@<suffix>. The prefix is a dot-separated list of
    //   non-empty words over [A-Za-z0-9_-], so it may not start or end with a
    //   dot and may not contain two consecutive dots.
    //
    // - The suffix is <prefix>.<domain>: split at the last dot, the part before
    //   must be a valid prefix and the domain must be 2 or 3 letters.
    //
    // - For each line print YES if it parses and NO otherwise.

    vector<string> results;
    for(const auto& email: emails) {
        results.push_back(is_valid_email(email) ? "YES" : "NO");
    }
    for(const auto& result: results) {
        cout << result << '\n';
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```



## 4. Python Solution

```python
import sys
import string

def is_symbol(ch):
    # Letters, digits, underscore or hyphen
    return ch.isalpha() or ch.isdigit() or ch in '_-'

def is_valid_prefix(pref):
    # Must be non-empty
    if not pref:
        return False
    # Cannot start or end with dot
    if pref[0] == '.' or pref[-1] == '.':
        return False
    last_dot = False
    for ch in pref:
        if ch == '.':
            # No consecutive dots
            if last_dot:
                return False
            last_dot = True
        else:
            # Every non-dot must be a symbol
            if not is_symbol(ch):
                return False
            last_dot = False
    return True

def is_valid_domain(dom):
    # Exactly 2 or 3 letters
    return len(dom) in (2, 3) and all(ch.isalpha() for ch in dom)

def is_valid_suffix(suf):
    # Must contain a dot dividing prefix and domain
    if '.' not in suf:
        return False
    # Split at the last dot
    i = suf.rfind('.')
    p = suf[:i]
    d = suf[i+1:]
    return is_valid_prefix(p) and is_valid_domain(d)

def is_valid_email(email):
    # Must contain a '@'
    if '@' not in email:
        return False
    i = email.find('@')
    p = email[:i]
    s = email[i+1:]
    return is_valid_prefix(p) and is_valid_suffix(s)

def main():
    data = sys.stdin.read().splitlines()
    n = int(data[0])
    for email in data[1:n+1]:
        print("YES" if is_valid_email(email) else "NO")

if __name__ == "__main__":
    main()
```



## 5. Compressed Editorial

Split on the `@`, check the left part and the segment before the last dot against the prefix rules: nonempty, no leading/trailing/consecutive dots, allowed symbols only. Afterward check the domain has length 2 or 3 letters. A stray second `@` is automatically rejected because `@` is not a valid prefix symbol.
