#include <bits/stdc++.h>
using namespace std;
#define ri register int
typedef long long ll;
namespace io {
	const int SIZE = (1 << 21) + 1;
	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
	// getchar
	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
	// print the remaining part
	inline void flush () {
		fwrite (obuf, 1, oS - obuf, stdout);
		oS = obuf;
	}
	// putchar
	inline void putc (char y) {
		*oS ++ = y;
		if (oS == oT) flush ();
	}
	// input a signed integer
	template <class I>
	inline void gi (I &y) {
		for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
		for (y = 0; c <= '9' && c >= '0'; c = gc()) y = (y << 1) + (y << 3) + (c & 15); y *= f;
	}
	// print a signed integer
	template <class I>
	inline void print (I y) {
		if (!y) putc ('0'); if (y < 0) putc ('-'), y = -y;
		while (y) qu[++ qr] = y % 10 + '0',  y /= 10;
		while (qr) putc (qu[qr --]);
	}
	// no need to call flush at the end manually!
	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
} 
using io :: gi;
using io :: putc;
using io :: print;
const int N=25e4+5,mod=1e9+7;
char s[N];
int x[6],power[6][N],xinv[6],powerinv[6][N];
inline void add(int &x,ri y){
	x=(x+=y)>=mod?x-mod:x;
}
inline void del(int &x,ri y){
	x=(x-=y)<0?x+mod:x;
}
struct node{
	int y[6];
	inline bool operator <(const node &rhs)const{
		for(ri i=0;i^6;++i)
			if(y[i]!=rhs.y[i])
				return y[i]<rhs.y[i];
		return 0;
	}
	inline void upd(ri p,ri k){
		ri i;
		if(p>=0){
			if(k==1){
				for(i=0;i^6;++i)
					add(y[i],power[i][p]);
			} 
			else{
				for(i=0;i^6;++i)
					del(y[i],power[i][p]);
			}
		}
		else{
			if(k==1){
				for(i=0;i^6;++i)
					add(y[i],powerinv[i][-p]);
			} 
			else{
				for(i=0;i^6;++i)
					del(y[i],powerinv[i][-p]);
			}
		}
	}
}res,res0,now;
struct orz{
	int k,b;
	inline void operator +=(const int &rhs){
		add(b,1);
	}
	inline void operator -=(const int &rhs){
		del(b,1);
	}
	inline void operator *=(const int &rhs){
		k=(ll)k*rhs%mod;
		b=(ll)b*rhs%mod;
	}
};
struct poly{
	orz f[6];
	inline void upd1(){
		for(ri i=0;i^6;++i)
			f[i]-=1;
	}
	inline void upd2(){
		for(ri i=0;i^6;++i)
			f[i]+=1;
	}
	inline void upd3(){
		for(ri i=0;i^6;++i)
			f[i]*=xinv[i];
	}
	inline void upd4(){
		for(ri i=0;i^6;++i)
			f[i]*=x[i];
	}
}resinv;
map<node,int> G;
inline int fpow(ri a,ri b){
	ri ans=1;
	for(;b;b>>=1,a=(ll)a*a%mod)
		if(b&1) ans=(ll)ans*a%mod;
	return ans;
}
int main(){
	srand(size_t(new char));
	ri n,i,j,nowp;
	register ll ans;
	scanf("%d%s",&n,s+1);
	for(i=0;i^6;++i){
		x[i]=rand()%(mod-1)+1; // linux 
		power[i][0]=1;
		for(j=1;j<=n;++j)
			power[i][j]=(ll)power[i][j-1]*x[i]%mod;
		xinv[i]=fpow(x[i],mod-2);
		powerinv[i][0]=1;
		for(j=1;j<=n;++j)
			powerinv[i][j]=(ll)powerinv[i][j-1]*xinv[i]%mod;
	}
	nowp=0;
	for(i=1;i<=n;++i)
		if(s[i]=='+')
			res0.upd(nowp,1);
		else if(s[i]=='-')
			res0.upd(nowp,-1);
		else if(s[i]=='>')
			++nowp;
		else
			--nowp;
	nowp=0;
	ans=0;
	for(i=0;i^6;++i) resinv.f[i].k=1;
	++G[res0];
	for(i=1;i<=n;++i){
		if(s[i]=='+')
			res.upd(nowp,1),
			resinv.upd1();
		else if(s[i]=='-')
			res.upd(nowp,-1),
			resinv.upd2();
		else if(s[i]=='>')
			++nowp,
			resinv.upd3();
		else
			--nowp,
			resinv.upd4();
		ans+=G[res];
		for(j=0;j^6;++j)
			now.y[j]=(ll)(res0.y[j]-resinv.f[j].b+mod)*fpow(resinv.f[j].k,mod-2)%mod;
		++G[now];
	}
	print(ans);putc('\n');
	return 0;
}

Measured memory_bytes: 51584