/*
* C++11 code template for contests.
* @author: Andrei Kalendarov
* @e-mail: andreykalendarov@gmail.com
*/

//#define ANDREIKKAA_ALLOCATOR
const int _ML = 228;

const char _inpf[] =
#if defined(ANDREIKKAA)
    "input.txt"
#else
    ""
#endif
;
const char _outf[] =
#if defined(ANDREIKKAA)
    ""
#else
    ""
#endif
;

#if defined(ANDREIKKAA)
#undef NDEBUG
#else
#pragma GCC optimize("O3,no-stack-protector")
#endif
#include <bits/stdc++.h>
#if !defined(ANDREIKKAA)
#define endl '\n'
#endif
#define x first
#define y second
using namespace std;
#define rand abcdefghijklmnopqrstuvwxyz
#define random_shuffle abcdefghijklmnopqrstuvwxyz
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double ld;
const ld PI = 3.14159265358979323846;
mt19937 rd(228);
#if defined(ANDREIKKAA_ALLOCATOR)
char _mem[_ML * 1024 * 1024];
size_t _ptr = 0;
inline void* operator new (size_t _x) { _ptr += _x; assert(_ptr < _ML * 1024 * 1024); return _mem + _ptr - _x; }
inline void operator delete (void*) { }
#endif
template<class T, class U> inline ostream &operator<< (ostream &, const pair<T, U> &);
template<class T, class U> inline istream &operator>> (istream &, pair<T, U> &);
template<class T> inline ostream &operator<< (ostream &, const vector<T> &);
template<class T> inline istream &operator>> (istream &, vector<T> &);
template<class T> inline ostream &operator<< (ostream &, const set<T> &);
template<class T> inline ostream &operator<< (ostream &, const multiset<T> &);
template<class T> inline ostream &operator<< (ostream &, const unordered_set<T> &);
template<class T> inline ostream &operator<< (ostream &, const unordered_multiset<T> &);
template<class T, class U> inline ostream &operator<< (ostream &, const map<T, U> &);
template<class T, class U> inline ostream &operator<< (ostream &, const unordered_map<T, U> &);

/* ________ CODE ________ */
const int X = 229;

struct hasher {
    vector<int> pw;
    int M;
    int val;

    int add(int a, int b) {
        return (a + b) % M;
    }

    int sub(int a, int b) {
        return (a - b + M) % M;
    }

    int mul(int a, int b) {
        return (int)(((ll)a * b) % M + M) % M;
    }

    int bp(int a, int b) {
        int r = 1;
        while(b) {
            if(b & 1) {
                r = mul(r, a);
            }
            a = mul(a, a);
            b >>= 1;
        }
        return r;
    }

    int div(int a, int b) {
        return mul(a, bp(b, M - 2));
    }

    hasher(int p, int m, int n) : M(m), val(0) {
        pw.resize(n);
        pw[0] = 1;
        for(int i = 1; i < n; ++i) {
            pw[i] = mul(pw[i - 1], p);
        }
    }

    void ins(int p, int x) {
        val = add(val, mul(pw[p], x));
    }

    void ers(int p, int x) {
        val = sub(val, mul(pw[p], x));
    }
};

inline void _main_function()
{
    int n;
    cin >> n;

    string s;
    cin >> s;

    vector<int> a(2 * n + 1);
    int p = n;

    hasher h(1000 * 1000 + 3, 1000 * 1000 * 1000 + 7, sz(a));
    hasher g(1000 * 1000 + 33, 1000 * 1000 * 1000 + 9, sz(a));

    vector<int> ah = {0}, ag = {0};

    for(int i = 0; i < n; ++i) {
        if(s[i] == '<') {
            --p;
        } else if(s[i] == '>') {
            ++p;
        } else {
            h.ers(p, a[p]);
            g.ers(p, a[p]);
            if(s[i] == '+') {
                ++a[p];
            } else if(s[i] == '-') {
                --a[p];
            } else {
                assert(false);
            }
            h.ins(p, a[p]);
            g.ins(p, a[p]);
        }

        ah.push_back(h.val);
        ag.push_back(g.val);
    }

    ll sum = 0;
    map<pair<int, int>, int> cnt;
    int sh = 0;

    for(int i = 0; i <= n; ++i) {
        sum += cnt[{ah[i], ag[i]}];

        if(i && s[i - 1] == '>') {
            ++sh;
        } else if(i && s[i - 1] == '<') {
            --sh;
        }

        if(sh >= 0) {
            int x = h.add(h.mul(ah.back(), h.pw[sh]), ah[i]);
            int y = g.add(g.mul(ag.back(), g.pw[sh]), ag[i]);
            ++cnt[{x, y}];
        } else {
            int x = h.add(h.div(ah.back(), h.pw[-sh]), ah[i]);
            int y = g.add(g.div(ag.back(), g.pw[-sh]), ag[i]);
            ++cnt[{x, y}];
        }
    }

    cout << sum << endl;
}

/* ________ CODE ________ */

int main()
{
#if defined(ANDREIKKAA)
    time_t _start = clock();
#endif
    if (_inpf[0] != '\0') assert(freopen(_inpf, "r", stdin) != nullptr);
    if (_outf[0] != '\0') assert(freopen(_outf, "w", stdout) != nullptr);
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    cout << setprecision(20);
    //cout << fixed;

    _main_function();
#if defined(ANDREIKKAA)
    cout << "Time: " << (clock() - _start) / (ld)CLOCKS_PER_SEC << endl;
#endif
}

template<class T, class U> inline ostream &operator<< (ostream &_out, const pair<T, U> &_p)
{
    _out << _p.x << ' ' << _p.y;
    return _out;
}
template<class T, class U> inline istream &operator>> (istream &_in, pair<T, U> &_p)
{
    _in >> _p.x >> _p.y;
    return _in;
}
template<class T> inline ostream &operator<< (ostream &_out, const vector<T> &_v)
{
    if (_v.empty()) { return _out; }
    _out << *_v.begin();
    for (auto _it = ++_v.begin(); _it != _v.end(); ++_it) { _out << ' ' << *_it; }
    return _out;
}
template<class T> inline istream &operator>> (istream &_in, vector<T> &_v)
{
    for (auto &_i : _v) { _in >> _i; }
    return _in;
}
template<class T> inline ostream &operator<< (ostream &_out, const set<T> &_s)
{
    if (_s.empty()) { return _out; }
    _out << *_s.begin();
    for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) { _out << ' ' << *_it; }
    return _out;
}
template<class T> inline ostream &operator<< (ostream &_out, const multiset<T> &_s)
{
    if (_s.empty()) { return _out; }
    _out << *_s.begin();
    for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) { _out << ' ' << *_it; }
    return _out;
}
template<class T> inline ostream &operator<< (ostream &_out, const unordered_set<T> &_s)
{
    if (_s.empty()) { return _out; }
    _out << *_s.begin();
    for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) { _out << ' ' << *_it; }
    return _out;
}
template<class T> inline ostream &operator<< (ostream &_out, const unordered_multiset<T> &_s)
{
    if (_s.empty()) { return _out; }
    _out << *_s.begin();
    for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) { _out << ' ' << *_it; }
    return _out;
}
template<class T, class U> inline ostream &operator<< (ostream &_out, const map<T, U> &_m)
{
    if (_m.empty()) { return _out; }
    _out << '(' << _m.begin()->x << ": " << _m.begin()->y << ')';
    for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) { _out << ", (" << _it->x << ": " << _it->y << ')'; }
    return _out;
}
template<class T, class U> inline ostream &operator<< (ostream &_out, const unordered_map<T, U> &_m)
{
    if (_m.empty()) { return _out; }
    _out << '(' << _m.begin()->x << ": " << _m.begin()->y << ')';
    for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) { _out << ", (" << _it->x << ": " << _it->y << ')'; }
    return _out;
}


Measured memory_bytes: 39560