Problem:
Score : 1200 points

Problem Statement

In Takahashi's mind, there is always an integer sequence of length 2 \times 10^9 + 1: A = (A_{-10^9}, A_{-10^9 + 1}, ..., A_{10^9 - 1}, A_{10^9}) and an integer P.

Initially, all the elements in the sequence A in Takahashi's mind are 0, and the value of the integer P is 0.

When Takahashi eats symbols +, -, > and <, the sequence A and the integer P will change as follows:

When he eats +, the value of A_P increases by 1;

When he eats -, the value of A_P decreases by 1;

When he eats >, the value of P increases by 1;

When he eats <, the value of P decreases by 1.

Takahashi has a string S of length N. Each character in S is one of the symbols +, -, > and <.
He chose a pair of integers (i, j) such that 1 \leq i \leq j \leq N and ate the symbols that are the i-th, (i+1)-th, ..., j-th characters in S, in this order.
We heard that, after he finished eating, the sequence A became the same as if he had eaten all the symbols in S from first to last.
How many such possible pairs (i, j) are there?

Constraints

1 \leq N \leq 250000

|S| = N

Each character in S is +, -, > or <.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the answer.

Sample Input 1

5
+>+<-

Sample Output 1

3

If Takahashi eats all the symbols in S, A_1 = 1 and all other elements would be 0.
The pairs (i, j) that leads to the same sequence A are as follows:

(1, 5)

(2, 3)

(2, 4)

Sample Input 2

5
+>+-<

Sample Output 2

5

Note that the value of P may be different from the value when Takahashi eats all the symbols in S.

Sample Input 3

48
-+><<><><><>>>+-<<>->>><<><<-+<>><+<<>+><-+->><<

Sample Output 3

475

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::collections::HashMap;
use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
struct XorShift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}
#[allow(dead_code)]
impl XorShift {
    fn new() -> XorShift {
        XorShift {
            x: 0x34fb2383,
            y: 0x327328fa,
            z: 0xabd4b54a,
            w: 0xa9dba8d1,
        }
    }
    fn seed(s: u32) -> XorShift {
        let mut rnd = XorShift::new();
        rnd.w = s;
        rnd
    }
    fn xor128(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
        self.w
    }
    fn next_i32(&mut self, r: i32) -> i32 {
        (self.xor128() % r as u32) as i32
    }
    fn next_i32_lr(&mut self, l: i32, r: i32) -> i32 {
        self.next_i32(r - l + 1) + l
    }
    fn next_i64(&mut self, r: i64) -> i64 {
        ((((self.xor128() as u64) << 32) + self.xor128() as u64) % r as u64) as i64
    }
    fn next_i64_lr(&mut self, l: i64, r: i64) -> i64 {
        self.next_i64(r - l + 1) + l
    }
    fn next_f64(&mut self, r: f64) -> f64 {
        (self.xor128() as f64) / (0xffffffffu32 as f64) * r
    }
    fn next_f64_lr(&mut self, l: f64, r: f64) -> f64 {
        self.next_f64(r - l) + l
    }
}

const MOD: i64 = 1e+9 as i64 + 7;
#[allow(dead_code)]
fn pow_mod(base: i64, power: i64, modulo: i64) -> i64 {
    let mut base = base;
    let mut power = power;
    let mut ans = 1;
    while power > 0 {
        if power & 1 == 1 {
            ans = ans * base % modulo;
        }
        power >>= 1;
        base = base * base % modulo;
    }
    ans
}

#[allow(dead_code)]
fn inv_mod(a: i64, modulo: i64) -> i64 {
    pow_mod(a, modulo - 2, modulo)
}

struct Solver {
    n: usize,
    s: Vec<char>,
    xs: Vec<i64>,
    aseq: Vec<Vec<i64>>,
    bseq: Vec<Vec<i64>>,
    ba: Vec<HashMap<i64, usize>>,
}

impl Solver {
    fn new(n: usize, s: Vec<char>) -> Solver {
        let mut rnd = XorShift::new();
        let mut xs = vec![0; 6];
        for i in 0..6 {
            xs[i] = rnd.next_i64(MOD);
        }
        let aseq = vec![vec![0; n + 1]; xs.len()];
        let bseq = vec![vec![0; n + 1]; xs.len()];
        let ba = vec![HashMap::<i64, usize>::new(); xs.len()];
        Solver {
            n: n,
            s: s,
            xs: xs,
            aseq: aseq,
            bseq: bseq,
            ba: ba,
        }
    }
    fn init(&mut self) {
        let n = self.n;
        for (i, &x) in self.xs.iter().enumerate() {
            let inv_x = inv_mod(x, MOD);
            self.aseq[i][n] = 1;
            self.bseq[i][n] = 0;
            for j in (0..n).rev() {
                let c = self.s[j];
                match c {
                    '+' => {
                        self.aseq[i][j] = self.aseq[i][j + 1];
                        self.bseq[i][j] = (self.bseq[i][j + 1] + 1) % MOD;
                    }
                    '-' => {
                        self.aseq[i][j] = self.aseq[i][j + 1];
                        self.bseq[i][j] = (self.bseq[i][j + 1] - 1 + MOD) % MOD;
                    }
                    '>' => {
                        self.aseq[i][j] = (self.aseq[i][j + 1] * x) % MOD;
                        self.bseq[i][j] = (self.bseq[i][j + 1] * x) % MOD;
                    }
                    '<' => {
                        self.aseq[i][j] = (self.aseq[i][j + 1] * inv_x) % MOD;
                        self.bseq[i][j] = (self.bseq[i][j + 1] * inv_x) % MOD;
                    }
                    _ => {
                        assert!(false);
                    }
                }
            }
        }
    }
    fn solve(&mut self) -> usize {
        self.init();
        let mut ans = 0;
        for i in 0..self.xs.len() {
            self.ba[i].insert(0, 1);
        }
        for i in (0..self.n).rev() {
            let mut cnt = self.n;
            for j in 0..self.xs.len() {
                let mut target = (self.bseq[j][i] - self.bseq[j][0] + MOD) % MOD
                    * inv_mod(self.aseq[j][i], MOD) % MOD;
                if let Some(&lcnt) = self.ba[j].get(&target) {
                    cnt = std::cmp::min(cnt, lcnt);
                } else {
                    cnt = 0;
                }
                let v = self.bseq[j][i] * inv_mod(self.aseq[j][i], MOD) % MOD;
                *self.ba[j].entry(v).or_insert(0) += 1;
            }
            // println!("{} {}", i, cnt);
            ans += cnt;
        }
        ans
    }
}

fn main() {
    let n = read::<usize>();
    let s = read::<String>().chars().collect::<Vec<char>>();
    let mut solver = Solver::new(n, s);
    let ans = solver.solve();
    println!("{}", ans);
}