#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,n) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) {
                        dp[l][r][cnt][dig]=-INF;
                        continue;
                    }
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            if(k+1>r&&cnt-1!=0) continue;
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,0,maxn-1) {
        rep(j,0,maxn-1) {
            rep(dig,0,1) {
                rep(cnt,0,maxn-1) {
                    int sum=0;
                    rep(k,i,j) {
                        if(s[k]==dig+'0') sum++;
                    }
                    if(sum<cnt) {
                        dp[i][j][cnt][dig]=-INF;
                    }
                }
            }
        }
    }
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,i) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) {
                        continue;
                    }
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            if(dp[k+1][r][cnt-1][dig]==-INF) continue;
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,0,maxn-1) {
        rep(j,0,maxn-1) {
            rep(dig,0,1) {
                rep(cnt,0,i) {
                    int sum=0;
                    rep(k,i,j) {
                        if(s[k]==dig+'0') sum++;
                    }
                    if(sum<cnt) {
                        dp[i][j][cnt][dig]=-INF;
                    }
                }
            }
        }
    }
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,i) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) {
                        dp[l][r][cnt][dig]=-INF;
                        continue;
                    }
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,0,maxn-1) {
        rep(j,0,maxn-1) {
            rep(dig,0,1) {
                rep(cnt,0,maxn-1) {
                    int sum=0;
                    rep(k,i,j) {
                        if(s[k]==dig+'0') sum++;
                    }
                    if(sum<cnt) {
                        dp[i][j][cnt][dig]=-INF;
                    }
                }
            }
        }
    }
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,i) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) continue;
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,i) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) {
                        dp[l][r][cnt][dig]=-INF;
                        continue;
                    }
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            if(k+1>r&&cnt-1!=0) continue;
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,i) memset(a,i,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const db exps=1e-8;
const db pi=acos(-1.0);
const int maxn=105;
const ll INF=0x3f3f3f3f3f3f3f3f;

ll ans[maxn][maxn];
ll dp[maxn][maxn][maxn][2];
ll a[maxn];
char s[maxn];
int n;

int main() {
    scanf("%d",&n);
    scanf("%s",s+1);
    rep(i,1,n) scanf("%lld",&a[i]);
    rep(i,0,maxn-1) {
        rep(j,0,maxn-1) {
            rep(dig,0,1) {
                rep(cnt,0,i) {
                    int sum=0;
                    rep(k,i,j) {
                        if(s[k]==dig+'0') sum++;
                    }
                    if(sum<cnt) {
                        dp[i][j][cnt][dig]=-INF;
                    }
                }
            }
        }
    }
    rep(i,1,n) {
        rep(j,1,n) {
            int l=j,r=j+i-1;
            if(r>n) continue;
            rep(dig,0,1) {
                rep(cnt,1,i) {
                    int sum=0;
                    rep(k,l,r) if(s[k]==dig+'0') sum++;
                    if(sum<cnt) {
                        continue;
                    }
                    rep(k,l,r) {
                        if(s[k]==dig+'0') {
                            if(dp[k+1][r][cnt-1][dig]==-INF) continue;
                            dp[l][r][cnt][dig]=max(ans[l][k-1]+dp[k+1][r][cnt-1][dig],dp[l][r][cnt][dig]);
                        }
                    }
                    ans[l][r]=max(ans[l][r],dp[l][r][cnt][dig]+a[cnt]);
                }
            }
            rep(dig,0,1) {
                dp[l][r][0][dig]=ans[l][r];
            }
        }
    }
    printf("%lld\n",ans[1][n]);
    return 0;
}


#include <cstdio>
#include <algorithm>

const int N = 100;
int n, a[N];
long long dp[N][N][N];
char s[N + 1];

long long run(int first, int last, int prev)
{
	long long &answer = dp[first][last - 1][prev];
	if (answer) return answer;
	if (last - first <= 0) return 0;
	answer = a[prev] + run(first + 1, last, 0);
	for (int i = first + 1; i < last; ++i) if (s[first] == s[i])
		answer = std::max(answer, run(first + 1, i, 0) + run(i, last, prev + 1));
	return answer;
}

int main()
{
	scanf("%d%s", &n, s);
	for (int i = 0; i < n; ++i) scanf("%d", a + i);
	printf("%lld\n", run(0, n, 0));
	return 0;
}


#include <cstdio>
#include <algorithm>

const int N = 100;
int n, a[N];
long long dp[N][N][N];
char s[N + 1];

long long run(int first, int last, int prev)
{
	if (last - first <= 0) return 0;
	long long &answer = dp[first][last - 1][prev];
	if (answer) return answer;
	answer = a[prev] + run(first + 1, last, 0);
	for (int i = first + 1; i < last; ++i) if (s[first] == s[i])
		answer = std::max(answer, run(first + 1, i, 0) + run(i, last, prev + 1));
	return answer;
}

int main()
{
	scanf("%d%s", &n, s);
	for (int i = 0; i < n; ++i) scanf("%d", a + i);
	printf("%lld\n", run(0, n, 0));
	return 0;
}


#include<bits/stdc++.h>
char c[204];
long long d[204][204][204];
int reward[204],n;
long long Max(long long a,long long b){return (a<b)?b:a;}
long long Min(long long  a,long long b){return (a<b)?a:b;}
long long f(int s,int e,int pre){
	if(e-s<=0) return 0;
	if(e-s==1) return reward[pre];
	if(d[s][e][pre]!=-1) return d[s][e][pre];
	int answer=reward[pre]+f(s+1,e,1);
	for(int i=s+1;i<n;i++){
		if(c[i]==c[s]){
			answer=Max(answer,f(s+1,i,1)+f(i,e,pre+1));
		}
	}
	return d[s][e][pre]=answer;
}
int main(){
	memset(d,-1,sizeof(d));
	scanf("%d",&n);
	scanf("%s",c);
	for(int i=1;i<=n;i++){
		scanf("%d",&reward[i]);
	}
	printf("%lld",f(0,n,1));
	return 0;
}


#include<bits/stdc++.h>
char c[204];
long long d[204][204][204];
int reward[204],n;
long long Max(long long a,long long b){return (a<b)?b:a;}
long long Min(long long  a,long long b){return (a<b)?a:b;}
long long f(int s,int e,int pre){
	if(e-s<=0) return 0;
	if(e-s==1) return reward[pre];
	if(d[s][e][pre]!=-1) return d[s][e][pre];
	int answer=reward[pre]+f(s+1,e,1);
	for(int i=s+1;i<e;i++){
		if(c[i]==c[s]){
			answer=Max(answer,f(s+1,i,1)+f(i,e,pre+1));
		}
	}
	return d[s][e][pre]=answer;
}
int main(){
	memset(d,-1,sizeof(d));
	scanf("%d",&n);
	scanf("%s",c);
	for(int i=1;i<=n;i++){
		scanf("%d",&reward[i]);
	}
	printf("%lld",f(0,n,1));
	return 0;
}


#include<bits/stdc++.h>
char c[204];
int d[204][204][204];
int reward[204],n;
long long Max(long long a,long long b){return (a<b)?b:a;}
long long Min(long long  a,long long b){return (a<b)?a:b;}
long long f(int s,int e,int pre){
	if(e-s<=0) return 0;
	if(e-s==1) return reward[pre];
	if(d[s][e][pre]!=-1) return d[s][e][pre];
	int answer=reward[pre]+f(s+1,e,1);
	for(int i=s+1;i<n;i++){
		if(c[i]==c[s]){
			answer=Max(answer,f(s+1,i,1)+f(i,e,pre+1));
		}
	}
	return d[s][e][pre]=answer;
}
int main(){
	memset(d,-1,sizeof(d));
	scanf("%d",&n);
	scanf("%s",c);
	for(int i=1;i<=n;i++){
		scanf("%d",&reward[i]);
	}
	printf("%lld",f(0,n,1));
	return 0;
}


#include<bits/stdc++.h>
char c[204];
long long d[204][204][204];
long long reward[204],n;
long long Max(long long a,long long b){return (a<b)?b:a;}
long long Min(long long  a,long long b){return (a<b)?a:b;}
long long f(int s,int e,int pre){
	if(e-s<=0) return 0;
	if(e-s==1) return reward[pre];
	if(d[s][e][pre]!=-1) return d[s][e][pre];
	long long answer=reward[pre]+f(s+1,e,1);
	for(int i=s+1;i<e;i++){
		if(c[i]==c[s]){
			answer=Max(answer,f(s+1,i,1)+f(i,e,pre+1));
		}
	}
	return d[s][e][pre]=answer;
}
int main(){
	memset(d,-1,sizeof(d));
	scanf("%lld",&n);
	scanf("%s",c);
	for(int i=1;i<=n;i++){
		scanf("%lld",&reward[i]);
	}
	printf("%lld",f(0,n,1));
	return 0;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define pii             pair<int , int >
#define in(a)           scanf("%d", &a)
#define in2(a, b)       scanf("%d%d", &a, &b)
#define in3(a, b, c)    scanf("%d%d%d", &a, &b, &c)
#define piil            pair<ll , ll >
#define inl(a)          scanf("%lld", &a)
#define inl2(a, b)      scanf("%lld%lld", &a, &b)
#define inl3(a, b, c)   scanf("%lld%lld%lld", &a, &b, &c)
#define ins(s)          scanf("%s",s)
#define prst(s)         printf("%s\n",s)
#define pn              printf("\n")
#define pr(a)           printf("%d\n", a)
#define prl(a)          printf("%lld\n", a)
#define prs(a)          printf("%d ", a)
#define pr2(a, b)       printf("%d %d\n", a, b)
#define pr3(a, b, c)    printf("%d %d %d\n", a, b, c)
#define prsl(a)         printf("%lld ", a)
#define prl2(a, b)      printf("%lld %lld\n", a, b)
#define prl3(a, b, c)   printf("%lld %lld %lld\n", a, b, c)
#define pcs(a)          printf("Case %d: ", a)
#define pf              printf
#define sc              scanf
#define m_p             make_pair
#define vi              vector<int >
#define vil             vector<ll >
#define pb              push_back
#define fi              first
#define sc              second
#define mem(a, b)       memset((a), (b), sizeof(a))
#define lg2(n)         (31-__builtin_clz(n))
#define PI		        acos(-1.0)
#define N 2000010
#define unq(v)       v.erase(unique(all(v)),v.end())
#define inf 2e18
#define ll long long
#define ull unsigned long long
#define fbo find_by_order
#define ook order_of_key
#define fi first
#define sc second
#define __  std::ios_base::sync_with_stdio (false); cin.tie(0); cout.tie(0);
#define Check(n, pos) (n & (1<<pos))
#define Set(n, pos) (n | (1<<pos))
ll gcd(ll a, ll b){if(b==0) {return a;}return gcd(b, a % b);}
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename F, typename S>
using ordered_map = tree<F, S, less<F>, rb_tree_tag, tree_order_statistics_node_update>;
#define debug(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); deb(_it, args); }
void deb(istream_iterator<string> it) {}
template<typename T, typename... Args>
void deb(istream_iterator<string> it, T a, Args... args) {
    cerr << *it << " = " << a << endl;
    deb(++it, args...);
}
ll BigMod(ll B,ll P,ll M){     ll R=1; while(P>0)      {if(P%2==1){R=(R*B)%M;}P/=2;B=(B*B)%M;} return R;}
//______________________________________________________________________________________________________________________________________________________
ll dp[110][110][110][2],arr[N],xx[350];
char str[N];
vi v;
int l;
ll rec(int i,int j,int k,int tp)
{
    //cout<<i<<" "<<j<<" "<<k<<" "<<tp<<endl;
    if(i>=j)
    {
        return xx[k+v[j]];
    }
    if(dp[i][j][k][tp]!=-1) return dp[i][j][k][tp];
    ll &ret=dp[i][j][k][tp];
    ret=0;
    for(int x=i+2;x<=j;x+=2)
    {
        ret=max(ret,rec(x,j,k+v[i],tp)+rec(i+1,x-1,0,tp^1));
    }
    ret=max(ret,rec(i+1,j,0,tp^1)+xx[k]);
    return ret;

}
ll rec2(int i)
{
    if(i==0)
        return 0;
        if(xx[i]!=-1) return xx[i];
        xx[i]=0;
    for(int j=1;j<=i;j++)
    {
        xx[i]=max(xx[i],arr[j]+rec2(i-j));
    }
    return xx[i];
}
int main()
{
  //  __;
   ll n,m,k,a,b,t;
   ll sum=0;
   string s;
   cin>>n;
   cin>>s;
   int cnt=1;
    mem(dp,-1);
   for(int i=0;i<n-1;i++)
   {
       if(s[i]==s[i+1])
       {
           cnt++;
       }
       else{
        v.pb(cnt);
        cnt=1;
       }
   }
   v.pb(cnt);
   v.pb(0);
   v.pb(0);
   l=v.size()-2;
   for(int i=1;i<=n;i++)
   {
       cin>>arr[i];
   }
   mem(xx,-1);
   rec2(n);
   ll g=rec(0,l-1,0,0);
   cout<<g<<endl;

    return 0;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define pii             pair<int , int >
#define in(a)           scanf("%d", &a)
#define in2(a, b)       scanf("%d%d", &a, &b)
#define in3(a, b, c)    scanf("%d%d%d", &a, &b, &c)
#define piil            pair<ll , ll >
#define inl(a)          scanf("%lld", &a)
#define inl2(a, b)      scanf("%lld%lld", &a, &b)
#define inl3(a, b, c)   scanf("%lld%lld%lld", &a, &b, &c)
#define ins(s)          scanf("%s",s)
#define prst(s)         printf("%s\n",s)
#define pn              printf("\n")
#define pr(a)           printf("%d\n", a)
#define prl(a)          printf("%lld\n", a)
#define prs(a)          printf("%d ", a)
#define pr2(a, b)       printf("%d %d\n", a, b)
#define pr3(a, b, c)    printf("%d %d %d\n", a, b, c)
#define prsl(a)         printf("%lld ", a)
#define prl2(a, b)      printf("%lld %lld\n", a, b)
#define prl3(a, b, c)   printf("%lld %lld %lld\n", a, b, c)
#define pcs(a)          printf("Case %d: ", a)
#define pf              printf
#define sc              scanf
#define m_p             make_pair
#define vi              vector<int >
#define vil             vector<ll >
#define pb              push_back
#define fi              first
#define sc              second
#define mem(a, b)       memset((a), (b), sizeof(a))
#define lg2(n)         (31-__builtin_clz(n))
#define PI		        acos(-1.0)
#define N 2000010
#define unq(v)       v.erase(unique(all(v)),v.end())
#define inf 2e18
#define ll long long
#define ull unsigned long long
#define fbo find_by_order
#define ook order_of_key
#define fi first
#define sc second
#define __  std::ios_base::sync_with_stdio (false); cin.tie(0); cout.tie(0);
#define Check(n, pos) (n & (1<<pos))
#define Set(n, pos) (n | (1<<pos))
ll gcd(ll a, ll b){if(b==0) {return a;}return gcd(b, a % b);}
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename F, typename S>
using ordered_map = tree<F, S, less<F>, rb_tree_tag, tree_order_statistics_node_update>;
#define debug(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); deb(_it, args); }
void deb(istream_iterator<string> it) {}
template<typename T, typename... Args>
void deb(istream_iterator<string> it, T a, Args... args) {
    cerr << *it << " = " << a << endl;
    deb(++it, args...);
}
ll BigMod(ll B,ll P,ll M){     ll R=1; while(P>0)      {if(P%2==1){R=(R*B)%M;}P/=2;B=(B*B)%M;} return R;}
//______________________________________________________________________________________________________________________________________________________
ll dp[110][110][110][2],arr[N],xx[150];
char str[N];
vi v;
int l;
ll rec(int i,int j,int k,int tp)
{
    //cout<<i<<" "<<j<<" "<<k<<" "<<tp<<endl;
    if(i>=j)
    {
        return xx[k+v[j]];
    }
    if(dp[i][j][k][tp]!=-1) return dp[i][j][k][tp];
    ll &ret=dp[i][j][k][tp];
    ret=0;
    for(int x=i+2;x<=j;x+=2)
    {
        ret=max(ret,rec(x,j,k+v[i],tp)+rec(i+1,x-1,0,tp^1));
    }
    ret=max(ret,rec(i+1,j,0,tp^1)+xx[k+v[i]]);
    return ret;

}
ll rec2(int i)
{
    if(i==0)
        return 0;
        if(xx[i]!=-1) return xx[i];
        xx[i]=0;
    for(int j=1;j<=i;j++)
    {
        xx[i]=max(xx[i],arr[j]+rec2(i-j));
    }
    return xx[i];
}
int main()
{
  //  __;
   ll n,m,k,a,b,t;
   ll sum=0;
   string s;
   cin>>n;
   cin>>s;
   int cnt=1;
    mem(dp,-1);
   for(int i=0;i<n-1;i++)
   {
       if(s[i]==s[i+1])
       {
           cnt++;
       }
       else{
        v.pb(cnt);
        cnt=1;
       }
   }
   v.pb(cnt);
   v.pb(0);
   v.pb(0);
   l=v.size()-2;
   for(int i=1;i<=n;i++)
   {
       cin>>arr[i];
   }
   mem(xx,-1);
   rec2(n+1);
   ll g=rec(0,l-1,0,0);
   cout<<g<<endl;

    return 0;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define pii             pair<int , int >
#define in(a)           scanf("%d", &a)
#define in2(a, b)       scanf("%d%d", &a, &b)
#define in3(a, b, c)    scanf("%d%d%d", &a, &b, &c)
#define piil            pair<ll , ll >
#define inl(a)          scanf("%lld", &a)
#define inl2(a, b)      scanf("%lld%lld", &a, &b)
#define inl3(a, b, c)   scanf("%lld%lld%lld", &a, &b, &c)
#define ins(s)          scanf("%s",s)
#define prst(s)         printf("%s\n",s)
#define pn              printf("\n")
#define pr(a)           printf("%d\n", a)
#define prl(a)          printf("%lld\n", a)
#define prs(a)          printf("%d ", a)
#define pr2(a, b)       printf("%d %d\n", a, b)
#define pr3(a, b, c)    printf("%d %d %d\n", a, b, c)
#define prsl(a)         printf("%lld ", a)
#define prl2(a, b)      printf("%lld %lld\n", a, b)
#define prl3(a, b, c)   printf("%lld %lld %lld\n", a, b, c)
#define pcs(a)          printf("Case %d: ", a)
#define pf              printf
#define sc              scanf
#define m_p             make_pair
#define vi              vector<int >
#define vil             vector<ll >
#define pb              push_back
#define fi              first
#define sc              second
#define mem(a, b)       memset((a), (b), sizeof(a))
#define lg2(n)         (31-__builtin_clz(n))
#define PI		        acos(-1.0)
#define N 2000010
#define unq(v)       v.erase(unique(all(v)),v.end())
#define inf 2e18
#define ll long long
#define ull unsigned long long
#define fbo find_by_order
#define ook order_of_key
#define fi first
#define sc second
#define __  std::ios_base::sync_with_stdio (false); cin.tie(0); cout.tie(0);
#define Check(n, pos) (n & (1<<pos))
#define Set(n, pos) (n | (1<<pos))
ll gcd(ll a, ll b){if(b==0) {return a;}return gcd(b, a % b);}
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename F, typename S>
using ordered_map = tree<F, S, less<F>, rb_tree_tag, tree_order_statistics_node_update>;
#define debug(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); deb(_it, args); }
void deb(istream_iterator<string> it) {}
template<typename T, typename... Args>
void deb(istream_iterator<string> it, T a, Args... args) {
    cerr << *it << " = " << a << endl;
    deb(++it, args...);
}
ll BigMod(ll B,ll P,ll M){     ll R=1; while(P>0)      {if(P%2==1){R=(R*B)%M;}P/=2;B=(B*B)%M;} return R;}
//______________________________________________________________________________________________________________________________________________________
ll dp[310][310][2],arr[N],xx[350];
char str[N];
vi v;
int l;
ll rec(int i,int j,int tp)
{
   // cout<<i<<" "<<j<<" "<<tp<<endl;
    if(i>=l)
    {
        return arr[j];
    }
    if(dp[i][j][tp]!=-1) return dp[i][j][tp];
    ll &ret=dp[i][j][tp];
    ret=0;
    ret=xx[j+v[i]];
    ret=max(ret,rec(i+2,j+v[i],tp)+xx[v[i+1]]);
    ret=max(ret,rec(i+1,0,tp^1)+xx[j]);

    return ret;

}
ll rec2(int i)
{
    if(i==0)
        return 0;
        if(xx[i]!=-1) return xx[i];
        xx[i]=0;
    for(int j=1;j<=i;j++)
    {
        xx[i]=max(xx[i],arr[j]+rec2(i-j));
    }
    return xx[i];
}
int main()
{
  //  __;
   ll n,m,k,a,b,t;
   ll sum=0;
   string s;
   cin>>n;
   cin>>s;
   int cnt=1;
    mem(dp,-1);
   for(int i=0;i<n-1;i++)
   {
       if(s[i]==s[i+1])
       {
           cnt++;
       }
       else{
        v.pb(cnt);
        cnt=1;
       }
   }
   v.pb(cnt);
   v.pb(0);
   v.pb(0);
   l=v.size();
   for(int i=1;i<=n;i++)
   {
       cin>>arr[i];
   }
   mem(xx,-1);
   rec2(n);
   ll g=rec(0,0,0);
   cout<<g<<endl;

    return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
#include<cassert>
#include<cmath>
#include<climits>
#include<iomanip>
#include<stack>
#include<unordered_map>
#include<bitset>
#include<limits>
#include<complex>
#include<array>
#include<numeric>
#include<functional>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rrep(i,m,n) for(ll (i)=(ll)(m);(i)>=(ll)(n);(i)--)
#define rep(i,m,n) for(ll (i)=(ll)(m);i<(ll)(n);i++)
#define REP(i,n) rep(i,0,n)
#define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i)
#define all(hoge) (hoge).begin(),(hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 62;
constexpr long double EPS = 1e-10;
template<typename T> using vector2 = vector<vector<T>>;
template<typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string& s, int k) {
	if (k == 0) return "";
	string p = (s + s) * (k / 2);
	if (k % 2 == 1) p += s;
	return p;
}

template<class T> inline bool chmin(T& a, T b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template<class T> inline bool chmax(T& a, T b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}

struct Edge {//グラフ
	int to, rev; ll cap;
	Edge(int _to, ll _cap, int _rev) {
		to = _to; cap = _cap; rev = _rev;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph& G, int from, int to, ll cap, bool revFlag, ll revCap) {//最大フロー求める Ford-fulkerson
	G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));//最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph& G, ll v, ll t, ll f, vector<bool>& used)
{
	if (v == t)
		return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); ++i) {
		Edge& e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
//二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph& G, ll s, ll t)//O(V(V+E))
{
	ll flow = 0;
	for (;;) {
		vector<bool> used(G.size());
		REP(i, used.size())used[i] = false;
		ll f = max_flow_dfs(G, s, t, INF, used);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

void BellmanFord(Graph& G, ll s, Array& d, Array& negative) {//O(|E||V|)
	d.resize(G.size());
	negative.resize(G.size());
	REP(i, d.size())d[i] = INF;
	REP(i, d.size())negative[i] = false;
	d[s] = 0;
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
				}
			}
		}
	}
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
					negative[G[i][j].to] = true;
				}
				if (negative[i] == true)negative[G[i][j].to] = true;
			}
		}
	}
}
void Dijkstra(Graph& G, ll s, Array& d) {//O(|E|log|V|)
	d.resize(G.size());
	REP(i, d.size())d[i] = INF;
	d[s] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(make_pair(0, s));
	while (!q.empty()) {
		P a = q.top();
		q.pop();
		if (d[a.second] < a.first)continue;
		REP(i, G[a.second].size()) {
			Edge e = G[a.second][i];
			if (d[e.to] > d[a.second] + e.cap) {
				d[e.to] = d[a.second] + e.cap;
				q.push(make_pair(d[e.to], e.to));
			}
		}
	}
}
void WarshallFloyd(Graph& G, Matrix& d) {//O(V^3)
	d.resize(G.size());
	REP(i, d.size())d[i].resize(G.size());
	REP(i, d.size()) {
		REP(j, d[i].size()) {
			d[i][j] = ((i != j) ? INF : 0);
		}
	}
	REP(i, G.size()) {
		REP(j, G[i].size()) {
			chmin(d[i][G[i][j].to], G[i][j].cap);
		}
	}
	REP(i, G.size()) {
		REP(j, G.size()) {
			REP(k, G.size()) {
				chmin(d[j][k], d[j][i] + d[i][k]);
			}
		}
	}
}
bool tsort(Graph& graph, Array& order) {//トポロジカルソートO(E+V)
	int n = graph.size(), k = 0;
	Array in(n);
	for (auto& es : graph)
		for (auto& e : es)in[e.to]++;
	priority_queue<ll, Array, greater<ll>> que;
	REP(i, n)
		if (in[i] == 0)que.push(i);
	while (que.size()) {
		int v = que.top();
		que.pop();
		order.push_back(v);
		for (auto& e : graph[v])
			if (--in[e.to] == 0)que.push(e.to);
	}
	if (order.size() != n)return false;
	else return true;
}
class Lca {
public:
	const int n = 0;
	const int log2_n = 0;
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;

	Lca() {}

	Lca(const Graph& g, int root)
		: n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n) {
		dfs(g, root, -1, 0);
		for (int k = 0; k + 1 < log2_n; k++) {
			for (int v = 0; v < (int)g.size(); v++) {
				if (parent[k][v] < 0)
					parent[k + 1][v] = -1;
				else
					parent[k + 1][v] = parent[k][parent[k][v]];
			}
		}
	}

	void dfs(const Graph& g, int v, int p, int d) {
		parent[0][v] = p;
		depth[v] = d;
		for (auto& e : g[v]) {
			if (e.to != p) dfs(g, e.to, v, d + 1);
		}
	}

	int get(int u, int v) {
		if (depth[u] > depth[v]) std::swap(u, v);
		for (int k = 0; k < log2_n; k++) {
			if ((depth[v] - depth[u]) >> k & 1) {
				v = parent[k][v];
			}
		}
		if (u == v) return u;
		for (int k = log2_n - 1; k >= 0; k--) {
			if (parent[k][u] != parent[k][v]) {
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
};

class UnionFind {
	vector<int> data;
	ll num;
public:
	UnionFind(int size) : data(size, -1), num(size) { }
	bool unite(int x, int y) {//xとyの集合を統合する
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		num -= (x != y);
		return x != y;
	}
	bool findSet(int x, int y) {//xとyが同じ集合か返す
		return root(x) == root(y);
	}
	int root(int x) {//xのルートを返す
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	ll size(int x) {//xの集合のサイズを返す
		return -data[root(x)];
	}
	ll numSet() {//集合の数を返す
		return num;
	}
};

template<typename T, typename F>
class SegmentTree {
private:
	T identity;
	F merge;
	ll n;
	vector<T> dat;
public:
	SegmentTree(F f, T id,vector<T> v) :merge(f), identity(id) {
		int _n = v.size();
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
		REP(i, _n)dat[n + i - 1] = v[i];
		for (int i = n - 2; i >= 0; i--)dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
	}
	SegmentTree(F f, T id, int _n) :merge(f), identity(id) {
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
	}
	void set_val(int i, T x) {
		i += n - 1;
		dat[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
		}
	}
	T query(int l, int r) {
		T left = identity, right = identity;
		l += n - 1; r += n - 1;
		while (l < r) {
			if ((l & 1) == 0)left = merge(left, dat[l]);
			if ((r & 1) == 0)right = merge(dat[r - 1], right);
			l = l / 2;
			r = (r - 1) / 2;
		}
		return merge(left, right);
	}
};

template< typename T >
class FenwickTree {
	vector< T > data;
	int n;
	int p;
public:
	FenwickTree(int n) :n(n) {
		data.resize(n + 1LL, 0);
		p = 1;
		while (p < data.size())p *= 2;
	}
	T sum(int k) {
		T ret = 0;
		for (; k > 0; k -= k & -k) ret += data[k];
		return (ret);
	}

	T sum(int a, int b) { return sum(b) - sum(a); }//[a,b)

	void add(int k, T x) {
		for (++k; k <= n; k += k & -k) data[k] += x;
	}

	int lower_bound(ll w) {
		if (w <= 0)return -1;
		int x = 0;
		for (int k = p / 2; k > 0; k /= 2) {
			if (x + k <= n && data[x + k] < w)w -= data[x + k], x += k;
		}
		return x;
	}
};

//約数求める //約数
void divisor(ll n, vector<ll>& ret) {
	for (ll i = 1; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) ret.push_back(n / i);
		}
	}
	sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P>& ret) {
	for (ll i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back({ i,0 });
			while (n % i == 0) {
				n /= i;
				ret[ret.size() - 1].second++;
			}
		}
	}
	if (n != 1)ret.push_back({ n,1 });
}

inline ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

inline ll mod_inv(ll x, ll mod) {
	return mod_pow(x, mod - 2, mod);
}

class Combination {
public:
	Array fact;
	Array fact_inv;
	ll mod;
	//if n >= mod use lucas
	ll nCr(ll n, ll r) {
		if (n < r)return 0;
		if (n < mod)return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

		ll ret = 1;
		while (n || r) {
			ll _n = n % mod, _r = r % mod;
			n /= mod; r /= mod;
			(ret *= nCr(_n, _r)) %= mod;
		}
		return ret;
	}
	ll nPr(ll n, ll r) {
		return (fact[n] * fact_inv[n - r]) % mod;
	}
	ll nHr(ll n, ll r) {
		return nCr(r + n - 1, r);
	}
	Combination(ll _n, ll _mod) {
		mod = _mod;
		ll n = min(_n + 1, mod);
		fact.resize(n);
		fact[0] = 1;
		REP(i, n - 1) {
			fact[i + 1] = (fact[i] * (i + 1LL)) % mod;
		}
		fact_inv.resize(n);
		fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
		for (int i = n - 1; i > 0; i--) {
			fact_inv[i - 1] = fact_inv[i] * i % mod;
		}
	}
};

ll popcount(ll x) {
	x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
	x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
	x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
	x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
	x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
	x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

	return x;
}

ll dp[110][110][110][2];

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	ll n;
	cin >> n;
	string s;
	cin >> s;
	Array a(n + 1, 0);
	REP(i, n)cin >> a[i + 1];

	auto solve = [&](auto solve, ll l, ll r, ll d, ll t)->ll {
		if (l >= r)return a[d];
		if (dp[l][r][d][t] != 0)return dp[l][r][d][t];
		ll ret = 0;
		chmax(ret, a[d] + solve(solve, l + 1, r, 1, s[l] - '0'));

		ll tmp = 0;
		ll m = INF;
		rep(i, l, r) {
			if (s[i] - '0' == t) {
				d++;
				tmp += solve(solve, m, i, 0, t ^ 1);
				chmax(ret, tmp + solve(solve, i + 1, r, d, t ^ 1));
				m = INF;
			}
			else chmin(m, i);
		}
		tmp += solve(solve, m, r, 0, t ^ 1);
		chmax(ret, tmp + a[d]);
		return dp[l][r][d][t] = ret;
	};
	cout << max(solve(solve, 0, n, 0, 0),solve(solve,0,n,0,1)) << "\n";

	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
#include<cassert>
#include<cmath>
#include<climits>
#include<iomanip>
#include<stack>
#include<unordered_map>
#include<bitset>
#include<limits>
#include<complex>
#include<array>
#include<numeric>
#include<functional>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rrep(i,m,n) for(ll (i)=(ll)(m);(i)>=(ll)(n);(i)--)
#define rep(i,m,n) for(ll (i)=(ll)(m);i<(ll)(n);i++)
#define REP(i,n) rep(i,0,n)
#define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i)
#define all(hoge) (hoge).begin(),(hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 62;
constexpr long double EPS = 1e-10;
template<typename T> using vector2 = vector<vector<T>>;
template<typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string& s, int k) {
	if (k == 0) return "";
	string p = (s + s) * (k / 2);
	if (k % 2 == 1) p += s;
	return p;
}

template<class T> inline bool chmin(T& a, T b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template<class T> inline bool chmax(T& a, T b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}

struct Edge {//グラフ
	int to, rev; ll cap;
	Edge(int _to, ll _cap, int _rev) {
		to = _to; cap = _cap; rev = _rev;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph& G, int from, int to, ll cap, bool revFlag, ll revCap) {//最大フロー求める Ford-fulkerson
	G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));//最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph& G, ll v, ll t, ll f, vector<bool>& used)
{
	if (v == t)
		return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); ++i) {
		Edge& e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
//二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph& G, ll s, ll t)//O(V(V+E))
{
	ll flow = 0;
	for (;;) {
		vector<bool> used(G.size());
		REP(i, used.size())used[i] = false;
		ll f = max_flow_dfs(G, s, t, INF, used);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

void BellmanFord(Graph& G, ll s, Array& d, Array& negative) {//O(|E||V|)
	d.resize(G.size());
	negative.resize(G.size());
	REP(i, d.size())d[i] = INF;
	REP(i, d.size())negative[i] = false;
	d[s] = 0;
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
				}
			}
		}
	}
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
					negative[G[i][j].to] = true;
				}
				if (negative[i] == true)negative[G[i][j].to] = true;
			}
		}
	}
}
void Dijkstra(Graph& G, ll s, Array& d) {//O(|E|log|V|)
	d.resize(G.size());
	REP(i, d.size())d[i] = INF;
	d[s] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(make_pair(0, s));
	while (!q.empty()) {
		P a = q.top();
		q.pop();
		if (d[a.second] < a.first)continue;
		REP(i, G[a.second].size()) {
			Edge e = G[a.second][i];
			if (d[e.to] > d[a.second] + e.cap) {
				d[e.to] = d[a.second] + e.cap;
				q.push(make_pair(d[e.to], e.to));
			}
		}
	}
}
void WarshallFloyd(Graph& G, Matrix& d) {//O(V^3)
	d.resize(G.size());
	REP(i, d.size())d[i].resize(G.size());
	REP(i, d.size()) {
		REP(j, d[i].size()) {
			d[i][j] = ((i != j) ? INF : 0);
		}
	}
	REP(i, G.size()) {
		REP(j, G[i].size()) {
			chmin(d[i][G[i][j].to], G[i][j].cap);
		}
	}
	REP(i, G.size()) {
		REP(j, G.size()) {
			REP(k, G.size()) {
				chmin(d[j][k], d[j][i] + d[i][k]);
			}
		}
	}
}
bool tsort(Graph& graph, Array& order) {//トポロジカルソートO(E+V)
	int n = graph.size(), k = 0;
	Array in(n);
	for (auto& es : graph)
		for (auto& e : es)in[e.to]++;
	priority_queue<ll, Array, greater<ll>> que;
	REP(i, n)
		if (in[i] == 0)que.push(i);
	while (que.size()) {
		int v = que.top();
		que.pop();
		order.push_back(v);
		for (auto& e : graph[v])
			if (--in[e.to] == 0)que.push(e.to);
	}
	if (order.size() != n)return false;
	else return true;
}
class Lca {
public:
	const int n = 0;
	const int log2_n = 0;
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;

	Lca() {}

	Lca(const Graph& g, int root)
		: n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n) {
		dfs(g, root, -1, 0);
		for (int k = 0; k + 1 < log2_n; k++) {
			for (int v = 0; v < (int)g.size(); v++) {
				if (parent[k][v] < 0)
					parent[k + 1][v] = -1;
				else
					parent[k + 1][v] = parent[k][parent[k][v]];
			}
		}
	}

	void dfs(const Graph& g, int v, int p, int d) {
		parent[0][v] = p;
		depth[v] = d;
		for (auto& e : g[v]) {
			if (e.to != p) dfs(g, e.to, v, d + 1);
		}
	}

	int get(int u, int v) {
		if (depth[u] > depth[v]) std::swap(u, v);
		for (int k = 0; k < log2_n; k++) {
			if ((depth[v] - depth[u]) >> k & 1) {
				v = parent[k][v];
			}
		}
		if (u == v) return u;
		for (int k = log2_n - 1; k >= 0; k--) {
			if (parent[k][u] != parent[k][v]) {
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
};

class UnionFind {
	vector<int> data;
	ll num;
public:
	UnionFind(int size) : data(size, -1), num(size) { }
	bool unite(int x, int y) {//xとyの集合を統合する
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		num -= (x != y);
		return x != y;
	}
	bool findSet(int x, int y) {//xとyが同じ集合か返す
		return root(x) == root(y);
	}
	int root(int x) {//xのルートを返す
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	ll size(int x) {//xの集合のサイズを返す
		return -data[root(x)];
	}
	ll numSet() {//集合の数を返す
		return num;
	}
};

template<typename T, typename F>
class SegmentTree {
private:
	T identity;
	F merge;
	ll n;
	vector<T> dat;
public:
	SegmentTree(F f, T id,vector<T> v) :merge(f), identity(id) {
		int _n = v.size();
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
		REP(i, _n)dat[n + i - 1] = v[i];
		for (int i = n - 2; i >= 0; i--)dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
	}
	SegmentTree(F f, T id, int _n) :merge(f), identity(id) {
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
	}
	void set_val(int i, T x) {
		i += n - 1;
		dat[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
		}
	}
	T query(int l, int r) {
		T left = identity, right = identity;
		l += n - 1; r += n - 1;
		while (l < r) {
			if ((l & 1) == 0)left = merge(left, dat[l]);
			if ((r & 1) == 0)right = merge(dat[r - 1], right);
			l = l / 2;
			r = (r - 1) / 2;
		}
		return merge(left, right);
	}
};

template< typename T >
class FenwickTree {
	vector< T > data;
	int n;
	int p;
public:
	FenwickTree(int n) :n(n) {
		data.resize(n + 1LL, 0);
		p = 1;
		while (p < data.size())p *= 2;
	}
	T sum(int k) {
		T ret = 0;
		for (; k > 0; k -= k & -k) ret += data[k];
		return (ret);
	}

	T sum(int a, int b) { return sum(b) - sum(a); }//[a,b)

	void add(int k, T x) {
		for (++k; k <= n; k += k & -k) data[k] += x;
	}

	int lower_bound(ll w) {
		if (w <= 0)return -1;
		int x = 0;
		for (int k = p / 2; k > 0; k /= 2) {
			if (x + k <= n && data[x + k] < w)w -= data[x + k], x += k;
		}
		return x;
	}
};

//約数求める //約数
void divisor(ll n, vector<ll>& ret) {
	for (ll i = 1; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) ret.push_back(n / i);
		}
	}
	sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P>& ret) {
	for (ll i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back({ i,0 });
			while (n % i == 0) {
				n /= i;
				ret[ret.size() - 1].second++;
			}
		}
	}
	if (n != 1)ret.push_back({ n,1 });
}

inline ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

inline ll mod_inv(ll x, ll mod) {
	return mod_pow(x, mod - 2, mod);
}

class Combination {
public:
	Array fact;
	Array fact_inv;
	ll mod;
	//if n >= mod use lucas
	ll nCr(ll n, ll r) {
		if (n < r)return 0;
		if (n < mod)return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

		ll ret = 1;
		while (n || r) {
			ll _n = n % mod, _r = r % mod;
			n /= mod; r /= mod;
			(ret *= nCr(_n, _r)) %= mod;
		}
		return ret;
	}
	ll nPr(ll n, ll r) {
		return (fact[n] * fact_inv[n - r]) % mod;
	}
	ll nHr(ll n, ll r) {
		return nCr(r + n - 1, r);
	}
	Combination(ll _n, ll _mod) {
		mod = _mod;
		ll n = min(_n + 1, mod);
		fact.resize(n);
		fact[0] = 1;
		REP(i, n - 1) {
			fact[i + 1] = (fact[i] * (i + 1LL)) % mod;
		}
		fact_inv.resize(n);
		fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
		for (int i = n - 1; i > 0; i--) {
			fact_inv[i - 1] = fact_inv[i] * i % mod;
		}
	}
};

ll popcount(ll x) {
	x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
	x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
	x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
	x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
	x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
	x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

	return x;
}

ll dp[110][110][110][2];

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	ll n;
	cin >> n;
	string s;
	cin >> s;
	Array a(n + 1, 0);
	REP(i, n)cin >> a[i + 1];
	REP(i, 110)REP(j, 110)REP(k, 110)REP(l, 2)dp[i][j][k][l] = -1;

	auto solve = [&](auto solve, ll l, ll r, ll d, ll t)->ll {
		ll dd = d;
		if (l >= r)return a[d];
		if (dp[l][r][d][t] != -1)return dp[l][r][d][t];
		ll ret = 0;
		chmax(ret, a[d] + solve(solve, l + 1, r, 1, s[l] - '0'));

		ll tmp = 0;
		ll m = INF;
		rep(i, l, r) {
			if (s[i] - '0' == t) {
				d++;
				tmp += solve(solve, m, i, 0, t ^ 1);
				chmax(ret, tmp + solve(solve, i + 1, r, d, t ^ 1));
				m = INF;
			}
			else chmin(m, i);
		}
		tmp += solve(solve, m, r, 0, t ^ 1);
		chmax(ret, tmp + a[d]);
		return dp[l][r][dd][t] = ret;
	};
	cout << max(solve(solve, 0, n, 0, 0),solve(solve,0,n,0,1)) << "\n";

	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
#include<cassert>
#include<cmath>
#include<climits>
#include<iomanip>
#include<stack>
#include<unordered_map>
#include<bitset>
#include<limits>
#include<complex>
#include<array>
#include<numeric>
#include<functional>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rrep(i,m,n) for(ll (i)=(ll)(m);(i)>=(ll)(n);(i)--)
#define rep(i,m,n) for(ll (i)=(ll)(m);i<(ll)(n);i++)
#define REP(i,n) rep(i,0,n)
#define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i)
#define all(hoge) (hoge).begin(),(hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 62;
constexpr long double EPS = 1e-10;
template<typename T> using vector2 = vector<vector<T>>;
template<typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string& s, int k) {
	if (k == 0) return "";
	string p = (s + s) * (k / 2);
	if (k % 2 == 1) p += s;
	return p;
}

template<class T> inline bool chmin(T& a, T b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template<class T> inline bool chmax(T& a, T b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}

struct Edge {//グラフ
	int to, rev; ll cap;
	Edge(int _to, ll _cap, int _rev) {
		to = _to; cap = _cap; rev = _rev;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph& G, int from, int to, ll cap, bool revFlag, ll revCap) {//最大フロー求める Ford-fulkerson
	G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));//最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph& G, ll v, ll t, ll f, vector<bool>& used)
{
	if (v == t)
		return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); ++i) {
		Edge& e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
//二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph& G, ll s, ll t)//O(V(V+E))
{
	ll flow = 0;
	for (;;) {
		vector<bool> used(G.size());
		REP(i, used.size())used[i] = false;
		ll f = max_flow_dfs(G, s, t, INF, used);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

void BellmanFord(Graph& G, ll s, Array& d, Array& negative) {//O(|E||V|)
	d.resize(G.size());
	negative.resize(G.size());
	REP(i, d.size())d[i] = INF;
	REP(i, d.size())negative[i] = false;
	d[s] = 0;
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
				}
			}
		}
	}
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
					negative[G[i][j].to] = true;
				}
				if (negative[i] == true)negative[G[i][j].to] = true;
			}
		}
	}
}
void Dijkstra(Graph& G, ll s, Array& d) {//O(|E|log|V|)
	d.resize(G.size());
	REP(i, d.size())d[i] = INF;
	d[s] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(make_pair(0, s));
	while (!q.empty()) {
		P a = q.top();
		q.pop();
		if (d[a.second] < a.first)continue;
		REP(i, G[a.second].size()) {
			Edge e = G[a.second][i];
			if (d[e.to] > d[a.second] + e.cap) {
				d[e.to] = d[a.second] + e.cap;
				q.push(make_pair(d[e.to], e.to));
			}
		}
	}
}
void WarshallFloyd(Graph& G, Matrix& d) {//O(V^3)
	d.resize(G.size());
	REP(i, d.size())d[i].resize(G.size());
	REP(i, d.size()) {
		REP(j, d[i].size()) {
			d[i][j] = ((i != j) ? INF : 0);
		}
	}
	REP(i, G.size()) {
		REP(j, G[i].size()) {
			chmin(d[i][G[i][j].to], G[i][j].cap);
		}
	}
	REP(i, G.size()) {
		REP(j, G.size()) {
			REP(k, G.size()) {
				chmin(d[j][k], d[j][i] + d[i][k]);
			}
		}
	}
}
bool tsort(Graph& graph, Array& order) {//トポロジカルソートO(E+V)
	int n = graph.size(), k = 0;
	Array in(n);
	for (auto& es : graph)
		for (auto& e : es)in[e.to]++;
	priority_queue<ll, Array, greater<ll>> que;
	REP(i, n)
		if (in[i] == 0)que.push(i);
	while (que.size()) {
		int v = que.top();
		que.pop();
		order.push_back(v);
		for (auto& e : graph[v])
			if (--in[e.to] == 0)que.push(e.to);
	}
	if (order.size() != n)return false;
	else return true;
}
class Lca {
public:
	const int n = 0;
	const int log2_n = 0;
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;

	Lca() {}

	Lca(const Graph& g, int root)
		: n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n) {
		dfs(g, root, -1, 0);
		for (int k = 0; k + 1 < log2_n; k++) {
			for (int v = 0; v < (int)g.size(); v++) {
				if (parent[k][v] < 0)
					parent[k + 1][v] = -1;
				else
					parent[k + 1][v] = parent[k][parent[k][v]];
			}
		}
	}

	void dfs(const Graph& g, int v, int p, int d) {
		parent[0][v] = p;
		depth[v] = d;
		for (auto& e : g[v]) {
			if (e.to != p) dfs(g, e.to, v, d + 1);
		}
	}

	int get(int u, int v) {
		if (depth[u] > depth[v]) std::swap(u, v);
		for (int k = 0; k < log2_n; k++) {
			if ((depth[v] - depth[u]) >> k & 1) {
				v = parent[k][v];
			}
		}
		if (u == v) return u;
		for (int k = log2_n - 1; k >= 0; k--) {
			if (parent[k][u] != parent[k][v]) {
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
};

class UnionFind {
	vector<int> data;
	ll num;
public:
	UnionFind(int size) : data(size, -1), num(size) { }
	bool unite(int x, int y) {//xとyの集合を統合する
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		num -= (x != y);
		return x != y;
	}
	bool findSet(int x, int y) {//xとyが同じ集合か返す
		return root(x) == root(y);
	}
	int root(int x) {//xのルートを返す
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	ll size(int x) {//xの集合のサイズを返す
		return -data[root(x)];
	}
	ll numSet() {//集合の数を返す
		return num;
	}
};

template<typename T, typename F>
class SegmentTree {
private:
	T identity;
	F merge;
	ll n;
	vector<T> dat;
public:
	SegmentTree(F f, T id,vector<T> v) :merge(f), identity(id) {
		int _n = v.size();
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
		REP(i, _n)dat[n + i - 1] = v[i];
		for (int i = n - 2; i >= 0; i--)dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
	}
	SegmentTree(F f, T id, int _n) :merge(f), identity(id) {
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
	}
	void set_val(int i, T x) {
		i += n - 1;
		dat[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
		}
	}
	T query(int l, int r) {
		T left = identity, right = identity;
		l += n - 1; r += n - 1;
		while (l < r) {
			if ((l & 1) == 0)left = merge(left, dat[l]);
			if ((r & 1) == 0)right = merge(dat[r - 1], right);
			l = l / 2;
			r = (r - 1) / 2;
		}
		return merge(left, right);
	}
};

template< typename T >
class FenwickTree {
	vector< T > data;
	int n;
	int p;
public:
	FenwickTree(int n) :n(n) {
		data.resize(n + 1LL, 0);
		p = 1;
		while (p < data.size())p *= 2;
	}
	T sum(int k) {
		T ret = 0;
		for (; k > 0; k -= k & -k) ret += data[k];
		return (ret);
	}

	T sum(int a, int b) { return sum(b) - sum(a); }//[a,b)

	void add(int k, T x) {
		for (++k; k <= n; k += k & -k) data[k] += x;
	}

	int lower_bound(ll w) {
		if (w <= 0)return -1;
		int x = 0;
		for (int k = p / 2; k > 0; k /= 2) {
			if (x + k <= n && data[x + k] < w)w -= data[x + k], x += k;
		}
		return x;
	}
};

//約数求める //約数
void divisor(ll n, vector<ll>& ret) {
	for (ll i = 1; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) ret.push_back(n / i);
		}
	}
	sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P>& ret) {
	for (ll i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back({ i,0 });
			while (n % i == 0) {
				n /= i;
				ret[ret.size() - 1].second++;
			}
		}
	}
	if (n != 1)ret.push_back({ n,1 });
}

inline ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

inline ll mod_inv(ll x, ll mod) {
	return mod_pow(x, mod - 2, mod);
}

class Combination {
public:
	Array fact;
	Array fact_inv;
	ll mod;
	//if n >= mod use lucas
	ll nCr(ll n, ll r) {
		if (n < r)return 0;
		if (n < mod)return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

		ll ret = 1;
		while (n || r) {
			ll _n = n % mod, _r = r % mod;
			n /= mod; r /= mod;
			(ret *= nCr(_n, _r)) %= mod;
		}
		return ret;
	}
	ll nPr(ll n, ll r) {
		return (fact[n] * fact_inv[n - r]) % mod;
	}
	ll nHr(ll n, ll r) {
		return nCr(r + n - 1, r);
	}
	Combination(ll _n, ll _mod) {
		mod = _mod;
		ll n = min(_n + 1, mod);
		fact.resize(n);
		fact[0] = 1;
		REP(i, n - 1) {
			fact[i + 1] = (fact[i] * (i + 1LL)) % mod;
		}
		fact_inv.resize(n);
		fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
		for (int i = n - 1; i > 0; i--) {
			fact_inv[i - 1] = fact_inv[i] * i % mod;
		}
	}
};

ll popcount(ll x) {
	x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
	x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
	x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
	x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
	x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
	x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

	return x;
}

ll dp[110][110][110][2];

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	ll n;
	cin >> n;
	string s;
	cin >> s;
	Array a(n + 1, 0);
	REP(i, n)cin >> a[i + 1];
	REP(i, 110)REP(j, 110)REP(k, 110)REP(l, 2)dp[i][j][k][l] = -1;

	auto solve = [&](auto solve, ll l, ll r, ll d, ll t)->ll {
		ll dd = d;
		if (l >= r)return 0;
		if (dp[l][r][d][t] != -1)return dp[l][r][d][t];
		ll ret = 0;
		chmax(ret, a[d] + solve(solve, l + 1, r, 1, s[l] - '0'));

		ll tmp = 0;
		ll m = INF;
		rep(i, l, r) {
			if (s[i] - '0' == t) {
				d++;
				tmp += solve(solve, m, i, 0, t ^ 1);
				chmax(ret, tmp + solve(solve, i + 1, r, d, t ^ 1));
				m = INF;
			}
			else chmin(m, i);
		}
		tmp += solve(solve, m, r, 0, t ^ 1);
		chmax(ret, tmp + a[d]);
		return dp[l][r][dd][t] = ret;
	};
	cout << max(solve(solve, 0, n, 0, 0),solve(solve,0,n,0,1)) << "\n";

	return 0;
}


#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
#include<cassert>
#include<cmath>
#include<climits>
#include<iomanip>
#include<stack>
#include<unordered_map>
#include<bitset>
#include<limits>
#include<complex>
#include<array>
#include<numeric>
#include<functional>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rrep(i,m,n) for(ll (i)=(ll)(m);(i)>=(ll)(n);(i)--)
#define rep(i,m,n) for(ll (i)=(ll)(m);i<(ll)(n);i++)
#define REP(i,n) rep(i,0,n)
#define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i)
#define all(hoge) (hoge).begin(),(hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 62;
constexpr long double EPS = 1e-10;
template<typename T> using vector2 = vector<vector<T>>;
template<typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string& s, int k) {
	if (k == 0) return "";
	string p = (s + s) * (k / 2);
	if (k % 2 == 1) p += s;
	return p;
}

template<class T> inline bool chmin(T& a, T b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
template<class T> inline bool chmax(T& a, T b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}

struct Edge {//グラフ
	int to, rev; ll cap;
	Edge(int _to, ll _cap, int _rev) {
		to = _to; cap = _cap; rev = _rev;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph& G, int from, int to, ll cap, bool revFlag, ll revCap) {//最大フロー求める Ford-fulkerson
	G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));//最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph& G, ll v, ll t, ll f, vector<bool>& used)
{
	if (v == t)
		return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); ++i) {
		Edge& e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
//二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph& G, ll s, ll t)//O(V(V+E))
{
	ll flow = 0;
	for (;;) {
		vector<bool> used(G.size());
		REP(i, used.size())used[i] = false;
		ll f = max_flow_dfs(G, s, t, INF, used);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

void BellmanFord(Graph& G, ll s, Array& d, Array& negative) {//O(|E||V|)
	d.resize(G.size());
	negative.resize(G.size());
	REP(i, d.size())d[i] = INF;
	REP(i, d.size())negative[i] = false;
	d[s] = 0;
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
				}
			}
		}
	}
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
					negative[G[i][j].to] = true;
				}
				if (negative[i] == true)negative[G[i][j].to] = true;
			}
		}
	}
}
void Dijkstra(Graph& G, ll s, Array& d) {//O(|E|log|V|)
	d.resize(G.size());
	REP(i, d.size())d[i] = INF;
	d[s] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(make_pair(0, s));
	while (!q.empty()) {
		P a = q.top();
		q.pop();
		if (d[a.second] < a.first)continue;
		REP(i, G[a.second].size()) {
			Edge e = G[a.second][i];
			if (d[e.to] > d[a.second] + e.cap) {
				d[e.to] = d[a.second] + e.cap;
				q.push(make_pair(d[e.to], e.to));
			}
		}
	}
}
void WarshallFloyd(Graph& G, Matrix& d) {//O(V^3)
	d.resize(G.size());
	REP(i, d.size())d[i].resize(G.size());
	REP(i, d.size()) {
		REP(j, d[i].size()) {
			d[i][j] = ((i != j) ? INF : 0);
		}
	}
	REP(i, G.size()) {
		REP(j, G[i].size()) {
			chmin(d[i][G[i][j].to], G[i][j].cap);
		}
	}
	REP(i, G.size()) {
		REP(j, G.size()) {
			REP(k, G.size()) {
				chmin(d[j][k], d[j][i] + d[i][k]);
			}
		}
	}
}
bool tsort(Graph& graph, Array& order) {//トポロジカルソートO(E+V)
	int n = graph.size(), k = 0;
	Array in(n);
	for (auto& es : graph)
		for (auto& e : es)in[e.to]++;
	priority_queue<ll, Array, greater<ll>> que;
	REP(i, n)
		if (in[i] == 0)que.push(i);
	while (que.size()) {
		int v = que.top();
		que.pop();
		order.push_back(v);
		for (auto& e : graph[v])
			if (--in[e.to] == 0)que.push(e.to);
	}
	if (order.size() != n)return false;
	else return true;
}
class Lca {
public:
	const int n = 0;
	const int log2_n = 0;
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;

	Lca() {}

	Lca(const Graph& g, int root)
		: n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n) {
		dfs(g, root, -1, 0);
		for (int k = 0; k + 1 < log2_n; k++) {
			for (int v = 0; v < (int)g.size(); v++) {
				if (parent[k][v] < 0)
					parent[k + 1][v] = -1;
				else
					parent[k + 1][v] = parent[k][parent[k][v]];
			}
		}
	}

	void dfs(const Graph& g, int v, int p, int d) {
		parent[0][v] = p;
		depth[v] = d;
		for (auto& e : g[v]) {
			if (e.to != p) dfs(g, e.to, v, d + 1);
		}
	}

	int get(int u, int v) {
		if (depth[u] > depth[v]) std::swap(u, v);
		for (int k = 0; k < log2_n; k++) {
			if ((depth[v] - depth[u]) >> k & 1) {
				v = parent[k][v];
			}
		}
		if (u == v) return u;
		for (int k = log2_n - 1; k >= 0; k--) {
			if (parent[k][u] != parent[k][v]) {
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
};

class UnionFind {
	vector<int> data;
	ll num;
public:
	UnionFind(int size) : data(size, -1), num(size) { }
	bool unite(int x, int y) {//xとyの集合を統合する
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		num -= (x != y);
		return x != y;
	}
	bool findSet(int x, int y) {//xとyが同じ集合か返す
		return root(x) == root(y);
	}
	int root(int x) {//xのルートを返す
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	ll size(int x) {//xの集合のサイズを返す
		return -data[root(x)];
	}
	ll numSet() {//集合の数を返す
		return num;
	}
};

template<typename T, typename F>
class SegmentTree {
private:
	T identity;
	F merge;
	ll n;
	vector<T> dat;
public:
	SegmentTree(F f, T id,vector<T> v) :merge(f), identity(id) {
		int _n = v.size();
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
		REP(i, _n)dat[n + i - 1] = v[i];
		for (int i = n - 2; i >= 0; i--)dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
	}
	SegmentTree(F f, T id, int _n) :merge(f), identity(id) {
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
	}
	void set_val(int i, T x) {
		i += n - 1;
		dat[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
		}
	}
	T query(int l, int r) {
		T left = identity, right = identity;
		l += n - 1; r += n - 1;
		while (l < r) {
			if ((l & 1) == 0)left = merge(left, dat[l]);
			if ((r & 1) == 0)right = merge(dat[r - 1], right);
			l = l / 2;
			r = (r - 1) / 2;
		}
		return merge(left, right);
	}
};

template< typename T >
class FenwickTree {
	vector< T > data;
	int n;
	int p;
public:
	FenwickTree(int n) :n(n) {
		data.resize(n + 1LL, 0);
		p = 1;
		while (p < data.size())p *= 2;
	}
	T sum(int k) {
		T ret = 0;
		for (; k > 0; k -= k & -k) ret += data[k];
		return (ret);
	}

	T sum(int a, int b) { return sum(b) - sum(a); }//[a,b)

	void add(int k, T x) {
		for (++k; k <= n; k += k & -k) data[k] += x;
	}

	int lower_bound(ll w) {
		if (w <= 0)return -1;
		int x = 0;
		for (int k = p / 2; k > 0; k /= 2) {
			if (x + k <= n && data[x + k] < w)w -= data[x + k], x += k;
		}
		return x;
	}
};

//約数求める //約数
void divisor(ll n, vector<ll>& ret) {
	for (ll i = 1; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) ret.push_back(n / i);
		}
	}
	sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P>& ret) {
	for (ll i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back({ i,0 });
			while (n % i == 0) {
				n /= i;
				ret[ret.size() - 1].second++;
			}
		}
	}
	if (n != 1)ret.push_back({ n,1 });
}

inline ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

inline ll mod_inv(ll x, ll mod) {
	return mod_pow(x, mod - 2, mod);
}

class Combination {
public:
	Array fact;
	Array fact_inv;
	ll mod;
	//if n >= mod use lucas
	ll nCr(ll n, ll r) {
		if (n < r)return 0;
		if (n < mod)return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

		ll ret = 1;
		while (n || r) {
			ll _n = n % mod, _r = r % mod;
			n /= mod; r /= mod;
			(ret *= nCr(_n, _r)) %= mod;
		}
		return ret;
	}
	ll nPr(ll n, ll r) {
		return (fact[n] * fact_inv[n - r]) % mod;
	}
	ll nHr(ll n, ll r) {
		return nCr(r + n - 1, r);
	}
	Combination(ll _n, ll _mod) {
		mod = _mod;
		ll n = min(_n + 1, mod);
		fact.resize(n);
		fact[0] = 1;
		REP(i, n - 1) {
			fact[i + 1] = (fact[i] * (i + 1LL)) % mod;
		}
		fact_inv.resize(n);
		fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
		for (int i = n - 1; i > 0; i--) {
			fact_inv[i - 1] = fact_inv[i] * i % mod;
		}
	}
};

ll popcount(ll x) {
	x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
	x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
	x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
	x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
	x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
	x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

	return x;
}

ll dp[110][110][110][2];

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	ll n;
	cin >> n;
	string s;
	cin >> s;
	Array a(n + 1, 0);
	REP(i, n)cin >> a[i + 1];
	REP(i, 110)REP(j, 110)REP(k, 110)REP(l, 2)dp[i][j][k][l] = -1;

	auto solve = [&](auto solve, ll l, ll r, ll d, ll t)->ll {
		if (l >= r)return a[d];
		if (dp[l][r][d][t] != -1)return dp[l][r][d][t];
		ll ret = 0;
		chmax(ret, a[d] + solve(solve, l + 1, r, 1, s[l] - '0'));
		rep(i, l, r) {
			if (s[i] - '0' == t) {
				chmax(ret, solve(solve, l, i, 0, t) + solve(solve, i + 1, r, d + 1, t));
			}
		}
		return dp[l][r][d][t] = ret;
	};
	cout << solve(solve, 0, n, 0, 0) << "\n";

	return 0;
}


//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define out(i,u) for(int i=first[u];i!=-1;i=next[i])
#define repvc(i,vc) for(int i=0,_sz=vc.size();i<sz;++i)
using namespace std;

const int INF=1<<30;
typedef long long ll;

inline int read()
{
	int ret=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
	return ret*f;
}

const int maxn=100+5;

ll dp[maxn][maxn][2][2][maxn];

int main()
{

}


//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define out(i,u) for(int i=first[u];i!=-1;i=next[i])
#define repvc(i,vc) for(int i=0,_sz=vc.size();i<sz;++i)
using namespace std;

const int INF=1<<30;
typedef long long ll;

inline int read()
{
	int ret=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
	return ret*f;
}

const int maxn=100+5;

ll dp[maxn][maxn][2][2][maxn];

int main()
{
	int n=100;
	rep(i,1,n) rep(j,1,n) rep(k,1,n){
		dp[i][j][0][0][k]=dp[i][j][0][1][k]=dp[i][j][1][0][k]=dp[i][j][1][1][k]=-INF;
	}
	return 0;
}


//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define out(i,u) for(int i=first[u];i!=-1;i=next[i])
#define repvc(i,vc) for(int i=0,_sz=vc.size();i<sz;++i)
using namespace std;

typedef long long ll;
const ll INF=1ll<<60;

inline int read()
{
	int ret=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
	return ret*f;
}

const int maxn=100+5;

ll dp[maxn][maxn][2][maxn],val[maxn];
int a[maxn],s[maxn];

ll DP(int l,int r,int b,int x)// b=number
{
//	printf("(l=%d,r=%d,b=%d,x=%d)\n",l,r,b,x);
	if(l>r) return x==0?0:-INF;
	ll &ans=dp[l][r][b][x];
	if(ans!=-1) return ans;

	int cnt=0;
	rep(i,l,r) if(s[i]==b) ++cnt;
	if(cnt<x) return ans=-INF;

	if(x>0)
	{
		rep(i,l,r) if(s[i]==b){
			ans=max(ans,DP(i+1,r,b,x-1)+DP(l,i-1,b,0));
		}
		for(int i=r;i>=l;--i) if(s[i]==b) ans=max(ans,DP(l,i-1,b,x-1)+DP(i+1,r,b,0));
	}
	else
	{
		int ok=1;
		rep(i,l,r) if(s[i]!=s[l]){ok=0;break;}
		if(ok) ans=val[r-l+1];
		else ans=0;
		rep(i,1,r-l+1)
			ans=max(ans,max(DP(l,r,1,i),DP(l,r,0,i))+val[i]);
	}
//	printf("(l=%d,r=%d,b=%d,x=%d)=%lld\n",l,r,b,x,ans);
	return ans;
}

int main()
{
	int n;cin>>n;
	memset(dp,-1,sizeof dp);
	rep(i,1,n) scanf("%01d",s+i);
	rep(i,1,n) scanf("%d",a+i);

	val[1]=a[1];
	rep(i,2,n)	{
		val[i]=a[i];
		rep(j,1,i-1)
			val[i]=max(val[i],val[j]+a[i-j]);
//		printf("val[%d]=%lld\n",i,val[i]);
	}

	ll ans=0;
	rep(i,1,n){
		ans=max(ans,DP(1,n,0,i)+val[i]);
		ans=max(ans,DP(1,n,1,i)+val[i]);
	}
	cout<<ans<<endl;
	return 0;
}


/*
Author: Dung Tuan Le
University of Rochester
*/

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define FOR(i, l, r) for (int i=l; i<=r; i++)
#define REP(i, r, l) for (int i=r; i>=l; i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define sz(x) int(x.size())
#define eps 1e-9

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int, int> pii;
typedef pair<long, long> pll;
typedef pair<ll, ll> pllll;
typedef pair<ld, ld> Point;
typedef pair<Point, Point> line;
struct strLine { ld a, b, c; };

typedef vector<int> vi;
typedef vector<long> vl;
typedef vector<ll> vll;

const double pi = 3.141592653589793;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0; y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b%a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll lcm(ll a, ll b) { return (a*b)/__gcd(a, b); }
inline ll max(ll a, ll b) { return (a>=b)?a:b; }
ll min(ll a, ll b) { return (a<=b)?a:b; }

#define maxn 100 + 10
ll dp[maxn][maxn][maxn], maxCon[maxn], a[maxn];
char s[maxn];

int main() {
	fio;
  long n; cin >> n;
  FOR(i, 1, n) cin >> s[i];
  FOR(i, 1, n) cin >> a[i];
  maxCon[1] = a[1];
  FOR(i, 2, n) FOR(j, 0, i - 1) maxCon[i] = max(maxCon[i], maxCon[j] + a[i - j]);
  // FOR(i, 2, n) FOR(j, 1, i - 1) {
  //   ll cnt = 0;
  //   FOR(t, j, i) if (s[i] == s[t]) cnt++;
  //   FOR(k, 1, cnt) {
  //     FOR(t, j, i) if (s[t] == s[i]) {
  //       ll tmp = 0;
  //       FOR(u, t + 1, i - 1) if (s[u] == s[i]) tmp++;
  //       ll maxSeg = 0;
  //       FOR(u, 1, tmp) maxSeg = max(maxSeg, dp[i - 1][t + 1][u]);
  //       dp[i][j][k] = max(dp[i][j][k], dp[t][j][k - 1] - maxCon[k - 1] + maxCon[k] + maxSeg);
  //     }
  //   }
  // }
  // ll res = 0;
  // FOR(i, 1, 100) res = max(res, dp[n][1][i]);
  // cout << res;
  // FOR(i, 1, n) FOR(j, 1, i) FOR(k, 1, 3) {
    // cout << i << " " << j << " " << k << " " << dp[i][j][k] << '\n';
  // }

  FOR(i, 1, n) dp[i][i][0] = maxCon[1];
  FOR(i, 2, n) FOR(j, 1, i - 1) {
    ll cnt = 0;
    FOR(t, j, i - 1) if (s[t] == s[i]) cnt++; // number of character than can erase at the time with s[i]
    FOR(k, 0, cnt) {
      if (k == 0) {
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][j][u]);
        dp[i][j][k] = max(dp[i][j][k], maxCon[1] + maxSeg);
        continue;
      }
      FOR(t, j, i - 1) if (s[t] == s[i]) {
        ll maxSeg = 0;
        FOR(u, 0, cnt) maxSeg = max(maxSeg, dp[i - 1][t + 1][u]);
        dp[i][j][k] = max(dp[i][j][k], dp[t][j][k - 1] - maxCon[k] + maxCon[k + 1] + maxSeg);
      }
    }
  }
  ll res = 0;
  FOR(i, 0, 100) res = max(res, dp[n][1][i]);
  cout << res << '\n';
	return 0;
}


/*
Author: Dung Tuan Le
University of Rochester
*/

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define FOR(i, l, r) for (int i=l; i<=r; i++)
#define REP(i, r, l) for (int i=r; i>=l; i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define sz(x) int(x.size())
#define eps 1e-9

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int, int> pii;
typedef pair<long, long> pll;
typedef pair<ll, ll> pllll;
typedef pair<ld, ld> Point;
typedef pair<Point, Point> line;
struct strLine { ld a, b, c; };

typedef vector<int> vi;
typedef vector<long> vl;
typedef vector<ll> vll;

const double pi = 3.141592653589793;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0; y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b%a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll lcm(ll a, ll b) { return (a*b)/__gcd(a, b); }
inline ll max(ll a, ll b) { return (a>=b)?a:b; }
ll min(ll a, ll b) { return (a<=b)?a:b; }

#define maxn 100 + 10
ll dp[maxn][maxn][maxn], maxCon[maxn], a[maxn];
char s[maxn];

int main() {
	// fio;
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  long n; cin >> n;
  FOR(i, 1, n) cin >> s[i];
  FOR(i, 1, n) cin >> a[i];
  FOR(i, 1, n) maxCon[i] = a[i];
  FOR(i, 2, n) FOR(j, 0, i - 1) maxCon[i] = max(maxCon[i], maxCon[j] + maxCon[i - j]);
  FOR(i, 1, n) dp[i][i][0] = maxCon[1];
  FOR(i, 2, n) FOR(j, 1, i - 1) {
    ll cnt = 0;
    FOR(t, j, i - 1) if (s[t] == s[i]) cnt++; // number of character than can erase at the time with s[i]
    FOR(k, 0, cnt) {
      if (k == 0) {
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][j][u]);
        dp[i][j][k] = max(dp[i][j][k], maxCon[1] + maxSeg);
        continue;
      }
      ll tmp = 0;
      FOR(t, j, i - 1) if (s[t] == s[i]) {
        tmp++;
        if (k > tmp) continue;
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][t + 1][u]);
        dp[i][j][k] = max(dp[i][j][k], dp[t][j][k - 1] - maxCon[k] + maxCon[k + 1] + maxSeg);
      }
    }
  }
  ll res = 0;
  // ll cnt = 0;
  // FOR(i, 1, n - 1) if (s[i] == s[n]) cnt++;
  FOR(i, 0, 100) res = max(res, dp[n][1][i]);
  cout << res;
  // FOR(i, 1, n) cout << maxCon[i] << " ";
  // FOR(i, 1, n) FOR(j, 1, i) {
    // ll cnt = 0;
    // FOR(k, j, i - 1) if (s[k] == s[i]) cnt++;
    // FOR(k, 0, 8) cout << i << " " << j << " " << k << " " << dp[i][j][k] << '\n';
  // }
  // fclose(stdin);
	return 0;
}


/*
Author: Dung Tuan Le
University of Rochester
*/

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define FOR(i, l, r) for (int i=l; i<=r; i++)
#define REP(i, r, l) for (int i=r; i>=l; i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define sz(x) int(x.size())
#define eps 1e-9

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int, int> pii;
typedef pair<long, long> pll;
typedef pair<ll, ll> pllll;
typedef pair<ld, ld> Point;
typedef pair<Point, Point> line;
struct strLine { ld a, b, c; };

typedef vector<int> vi;
typedef vector<long> vl;
typedef vector<ll> vll;

const double pi = 3.141592653589793;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0; y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b%a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll lcm(ll a, ll b) { return (a*b)/__gcd(a, b); }
inline ll max(ll a, ll b) { return (a>=b)?a:b; }
ll min(ll a, ll b) { return (a<=b)?a:b; }

#define maxn 100 + 10
ll dp[maxn][maxn][maxn], maxCon[maxn], a[maxn];
char s[maxn];

int main() {
	fio;
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
  long n; cin >> n;
  FOR(i, 1, n) cin >> s[i];
  FOR(i, 1, n) cin >> a[i];
  // maxCon[1] = a[1];
  FOR(i, 1, n) maxCon[i] = a[i];
  FOR(i, 2, n) FOR(j, 0, i - 1) maxCon[i] = max(maxCon[i], maxCon[j] + maxCon[i - j]);
  FOR(i, 1, n) dp[i][i][0] = maxCon[1];
  FOR(i, 2, n) FOR(j, 1, i - 1) {
    ll cnt = 0;
    FOR(t, j, i - 1) if (s[t] == s[i]) cnt++; // number of character than can erase at the time with s[i]
    FOR(k, 0, cnt) {
      if (k == 0) {
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][j][u]);
        dp[i][j][k] = max(dp[i][j][k], maxCon[1] + maxSeg);
        continue;
      }
      FOR(t, j, i - 1) if (s[t] == s[i]) {
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][t + 1][u]);
        dp[i][j][k] = max(dp[i][j][k], dp[t][j][k - 1] - maxCon[k] + maxCon[k + 1] + maxSeg);
      }
    }
  }
  ll res = 0;
  // ll cnt = 0;
  // FOR(i, 1, n - 1) if (s[i] == s[n]) cnt++;
  FOR(i, 0, 100) res = max(res, dp[n][1][i]);
  cout << res;
  // cout << maxCon[8];
  // FOR(i, 1, n) cout << maxCon[i] << " ";
  FOR(i, 1, n) FOR(j, 1, i) {
    ll cnt = 0;
    FOR(k, j, i - 1) if (s[k] == s[i]) cnt++;
    // FOR(k, 0, cnt) cout << i << " " << j << " " << k << " " << dp[i][j][k] << '\n';
  }
  // fclose(stdin);
	return 0;
}


/*
Author: Dung Tuan Le
University of Rochester
*/

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define FOR(i, l, r) for (int i=l; i<=r; i++)
#define REP(i, r, l) for (int i=r; i>=l; i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define sz(x) int(x.size())
#define eps 1e-9

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int, int> pii;
typedef pair<long, long> pll;
typedef pair<ll, ll> pllll;
typedef pair<ld, ld> Point;
typedef pair<Point, Point> line;
struct strLine { ld a, b, c; };

typedef vector<int> vi;
typedef vector<long> vl;
typedef vector<ll> vll;

const double pi = 3.141592653589793;

ll gcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0) {
        x = 0; y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd(b%a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll lcm(ll a, ll b) { return (a*b)/__gcd(a, b); }
inline ll max(ll a, ll b) { return (a>=b)?a:b; }
ll min(ll a, ll b) { return (a<=b)?a:b; }

#define maxn 100 + 10
ll dp[maxn][maxn][maxn], maxCon[maxn], a[maxn];
char s[maxn];

int main() {
	fio;
  long n; cin >> n;
  FOR(i, 1, n) cin >> s[i];
  FOR(i, 1, n) cin >> a[i];
  FOR(i, 1, n) maxCon[i] = a[i];
  FOR(i, 2, n) FOR(j, 0, i - 1) maxCon[i] = max(maxCon[i], maxCon[j] + maxCon[i - j]);
  FOR(i, 1, n) dp[i][i][0] = maxCon[1];
  FOR(i, 2, n) FOR(j, 1, i - 1) {
    ll cnt = 0;
    FOR(t, j, i - 1) if (s[t] == s[i]) cnt++; // number of character than can erase at the time with s[i]
    FOR(k, 0, cnt) {
      if (k == 0) {
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][j][u]);
        dp[i][j][k] = max(dp[i][j][k], maxCon[1] + maxSeg);
        continue;
      }
      ll tmp = 0;
      FOR(t, j, i - 1) if (s[t] == s[i]) {
        tmp++;
        if (k > tmp) continue;
        ll maxSeg = 0;
        FOR(u, 0, 100) maxSeg = max(maxSeg, dp[i - 1][t + 1][u]);
        dp[i][j][k] = max(dp[i][j][k], dp[t][j][k - 1] - maxCon[k] + maxCon[k + 1] + maxSeg);
      }
    }
  }
  ll res = 0;
  FOR(i, 0, 100) res = max(res, dp[n][1][i]);
  cout << res;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int score[110];
long long dp[110][110][110];
string s;
int n;

long long getMax(int l, int r, int len)
{
    if (l == r) return score[len];

    if (l > r) return 0;

    long long &ret = dp[l][r][len];
    if (ret != -1) return ret;

    ret = getMax(l+1, r, 1) + score[len];

    for (int i = l+1; i <= r; i++)
        if (s[l] == s[i])
            ret = max(ret, getMax(l+1, i-1, 1) + getMax(i, r, len+1));

    return ret;
}

int main()
{
    cin >> n;
    cin >> s;
    for (int i = 1; i <= n; i++) cin >> score[i];

    memset(dp, -1, sizeof dp);

    cout << getMax(0, n-1, 1);
}


#include <bits/stdc++.h>

using namespace std;

int score[110];
long long dp[110][110][110];
string s;
int n;

long long getMax(int l, int r, int len)
{
    if (l == r) return score[len];

    if (l > r) return 0;

    int &ret = dp[l][r][len];
    if (ret != -1) return ret;

    ret = getMax(l+1, r, 1) + score[len];

    for (int i = l+1; i <= r; i++)
        if (s[l] == s[i])
            ret = max(ret, getMax(l+1, i-1, 1) + getMax(i, r, len+1));

    return ret;
}

int main()
{
    cin >> n;
    cin >> s;
    for (int i = 1; i <= n; i++) cin >> score[i];

    memset(dp, -1, sizeof dp);

    cout << getMax(0, n-1, 1);
}


#include <bits/stdc++.h>

using namespace std;

unsigned long long score[110];
map<string, unsigned long long> mem;

string subtract(const string &s, int start, int end)
{
    return s.substr(0, start) + s.substr(end, s.length() - end);
}

unsigned long long getMax(const string &s)
{
    if (s.empty()) return 0;

    if (mem.find(s) != mem.end())
        return mem[s];

    unsigned long long mx = 0;
    int len = 0, start = 0;
    for (int i = 0; i < s.length(); i++)
    {
        len++;
        mx = max(mx, score[len] + getMax(subtract(s, start, start+len)));
        if (i < s.length() - 1 && s[i] != s[i+1])
        {
            len = 0;
            start = i;
        }
    }

    return mem[s] = mx;
}

int main()
{
    int n; cin >> n;
    string s; cin >> s;
    for (int i = 1; i <= n; i++) cin >> score[i];

    cout << getMax(s);
}


#include <bits/stdc++.h>

using namespace std;

int score[110];
int dp[110][110][110];
string s;
int n;

int getMax(int l, int r, int len)
{
    if (l == r) return score[len];

    if (l > r) return 0;

    int &ret = dp[l][r][len];
    if (ret != -1) return ret;

    ret = getMax(l+1, r, 1) + score[len];

    for (int i = l+1; i <= r; i++)
        if (s[l] == s[i])
            ret = max(ret, getMax(l+1, i-1, 1) + getMax(i, r, len+1));

    return ret;
}

int main()
{
    cin >> n;
    cin >> s;
    for (int i = 1; i <= n; i++) cin >> score[i];

    memset(dp, -1, sizeof dp);

    cout << getMax(0, n-1, 1);
}


#include <bits/stdc++.h>

using namespace std;

unsigned long long score[110];
map<string, unsigned long long> mem;

string subtract(const string &s, int start, int end)
{
    return s.substr(0, start) + s.substr(end, s.length() - end);
}

unsigned long long getMax(const string &s)
{
    if (s.empty()) return 0;

    if (mem.find(s) != mem.end())
        return mem[s];

    unsigned long long mx = 0;
    int len = 0, start = 0;
    for (int i = 0; i < s.length(); i++)
    {
        len++;
        mx = max(mx, score[len] + getMax(subtract(s, start, start+len)));
        if (i < s.length() - 1 && s[i] != s[i+1])
        {
            len = 0;
            start = i;
        }
    }

    return mem[s] = mx;
}

int main()
{
    int n; cin >> n;
    string s; cin >> s;
    for (int i = 1; i < n; i++) cin >> score[i];

    cout << getMax(s);
}


#include <cstdio>
#include <queue>
using namespace std;

bool getBit(){
	for(char c=getchar();;c=getchar()){
		if(c=='0')
			return 0;
		if(c=='1')
			return 1;
	}
}
vector <bool> s;
vector <long long> a;
const long long undef=-100000000001;
const long long neginf=-100000000000;
long long memo[100][101][101][2];
long long solve(int l, int r, int count=0, bool digit=false){
	if(count==0)
		digit=false;
	long long&ret=memo[l][r][count][digit];
	if(ret==undef){
		if(r-l==0){
			ret=(count?neginf:0);
		}else if(count){
			for(int i = l;i < r;i ++){//possible firsts of count digits
				if(s[i]!=digit)
					continue;
				ret=max(ret, solve(l, i)+solve(i+1, r, count-1, digit));
			}
		}else{
			for(int i = 1;i <= r-l;i ++){//possible last clear counts
				ret=max(ret, a[i-1]+solve(l, r, i, false));
				ret=max(ret, a[i-1]+solve(l, r, i, true));
			}
		}
	}
	return ret;
}
int main(){
	int n;
	scanf("%d", &n);
	s.resize(n);
	for(int i = 0;i < n;i ++)
		s[i]=getBit();
	a.resize(n);
	for(auto&i:a)
		scanf("%lld", &i);
	for(auto&i:memo)for(auto&j:i)for(auto&k:j)for(auto&l:k){
		l=undef;
	}
	printf("%lld\n", solve(0, n));
}


#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;

bool getBit(){
	for(char c=getchar();;c=getchar()){
		if(c=='0')
			return 0;
		if(c=='1')
			return 1;
	}
}
vector <bool> s;
vector <long long> a;
const long long undef=-100000000001;
const long long neginf=-100000000000;
long long memo[100][101][101][2];
long long solve(int l, int r, int count=0, bool digit=false){
	if(count==0)
		digit=false;
	long long&ret=memo[l][r][count][digit];
	if(ret==undef){
		if(r-l==0){
			ret=(count?neginf:0);
		}else if(count){
			for(int i = l;i < r;i ++){//possible firsts of count digits
				if(s[i]!=digit)
					continue;
				ret=max(ret, solve(l, i)+solve(i+1, r, count-1, digit));
			}
		}else{
			for(int i = 1;i <= r-l;i ++){//possible last clear counts
				ret=max(ret, a[i-1]+solve(l, r, i, false));
				ret=max(ret, a[i-1]+solve(l, r, i, true));
			}
		}
	}
	return ret;
}
int main(){
	int n;
	scanf("%d", &n);
	s.resize(n);
	for(int i = 0;i < n;i ++)
		s[i]=getBit();
	a.resize(n);
	for(auto&i:a)
		scanf("%lld", &i);
	for(int i = 2;i <= n;i ++){
		for(int j = 1;j+j<=i;j ++){
			a[i-1]=max(a[i-1], a[j-1]+a[i-j-1]);
		}
	}
	for(auto&i:memo)for(auto&j:i)for(auto&k:j)for(auto&l:k){
		l=undef;
	}
	printf("%lld\n", solve(0, n));
}


#include <cstdio>
#include <queue>
using namespace std;

bool getBit(){
	for(char c=getchar();;c=getchar()){
		if(c=='0')
			return 0;
		if(c=='1')
			return 1;
	}
}
vector <bool> s;
vector <int> a;
const long long undef=-100000000001;
const long long neginf=-100000000000;
long long memo[101][101][101][2];
long long solve(int l, int r, int count=0, bool digit=false){
	if(count==0)
		digit=false;
	long long&ret=memo[l][r][count][digit];
	if(ret==undef){
		if(r-l==0){
			ret=(count?neginf:0);
		}else if(count){
			for(int i = l;i < r;i ++){//possible firsts of count digits
				if(s[i]!=digit)
					continue;
				ret=max(ret, solve(l, i)+solve(i+1, r, count-1, digit));
			}
		}else{
			for(int i = 1;i <= r-l;i ++){//possible last clear counts
				ret=max(ret, a[i-1]+solve(l, r, i, false));
				ret=max(ret, a[i-1]+solve(l, r, i, true));
			}
		}
	}
	return ret;
}
int main(){
	int n;
	scanf("%d", &n);
	s.resize(n);
	for(int i = 0;i < n;i ++)
		s[i]=getBit();
	a.resize(n);
	for(int&i:a)
		scanf("%d", &i);
	for(auto&i:memo)for(auto&j:i)for(auto&k:j)for(auto&l:k){
		l=undef;
	}
	printf("%lld\n", solve(0, n));
}


#include <cstdio>
#include <queue>
using namespace std;

bool getBit(){
	for(char c=getchar();;c=getchar()){
		if(c=='0')
			return 0;
		if(c=='1')
			return 1;
	}
}
vector <bool> s;
vector <int> a;
const long long undef=-100000000001;
const long long neginf=-100000000000;
long long memo[101][101][101][2];
long long solve(int l, int r, int count=0, bool digit=false){
	if(count==0)
		digit=false;
	long long&ret=memo[l][r][count][digit];
	if(ret==undef){
		if(r-l==0){
			ret=(count?neginf:0);
		}else if(count){
			for(int i = l;i < r;i ++){//possible firsts of count digits
				if(s[i]!=digit)
					continue;
				ret=max(ret, solve(l, i)+solve(i+1, r, count-1, digit));
			}
		}else{
			for(int i = 1;i <= r-l;i ++){//possible last clear counts
				ret=max(ret, a[i-1]+solve(l, r, i, false));
				ret=max(ret, a[i-1]+solve(l, r, i, true));
			}
		}
	}
	return ret;
}
int main(){
	int n;
	scanf("%d", &n);
	s.resize(n);
	for(int i = 0;i < n;i ++)
		s[i]=getBit();
	a.resize(n);
	for(int&i:a)
		scanf("%lld", &i);
	for(auto&i:memo)for(auto&j:i)for(auto&k:j)for(auto&l:k){
		l=undef;
	}
	printf("%lld\n", solve(0, n));
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

string s;
int n;
ll dp[105][105], a[105];

ll inner0[105][105], inner1[105][105];

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

	cin >> n >> s;
	for (int i=1; i<=n; i++)
		cin >> a[i];
	s = string(" ") + s + string(" ");

	for (int l=n; l>=1; l--) {
		for (int r=l; r<=n; r++) {

			memset(inner0, 128, sizeof(inner0));
			memset(inner1, 128, sizeof(inner1));

			inner0[l-1][0] = inner1[l-1][0] = 0;

			for (int i=l; i<=r; i++) {
				// mogu da samo uzmem ovo ako je kec
				if (s[i] == '1')
					for (int x=1; x<=i-l+1; x++)
						inner1[i][x] = max(inner1[i][x], inner1[i-1][x-1]);
				// spoji unazad
				for (int x=0; x<=i-l+1; x++)
					for (int j=i; j>=l; j--)
						inner1[i][x] = max(inner1[i][x], inner1[j-1][x] + dp[j][i]);
			}

			for (int i=l; i<=r; i++) {
				// mogu da samo uzmem ovo ako je kec
				if (s[i] == '0')
					for (int x=1; x<=i-l+1; x++)
						inner0[i][x] = max(inner0[i][x], inner0[i-1][x-1]);
				// spoji unazad
				for (int x=0; x<=i-l+1; x++)
					for (int j=i; j>=l; j--)
						inner0[i][x] = max(inner0[i][x], inner0[j-1][x] + dp[j][i]);
			}

			for (int x=0; x<=r-l+1; x++) {
				dp[l][r] = max(dp[l][r], inner0[r][x] + a[x]);
				dp[l][r] = max(dp[l][r], inner1[r][x] + a[x]);
			}
		}
	}
	cout << dp[1][n] << '\n';
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

string s;
int n;
ll dp[105][105], a[105];

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

	cin >> n >> s;
	for (int i=1; i<=n; i++)
		cin >> a[i];
	s = string(" ") + s + string(" ");

	for (int l=n; l>=1; l--) {
		for (int r=l; r<=n; r++) {
			ll& d = dp[l][r];
			if (l == r) {
				d = a[1];
			} else {
				// split?
				for (int m=l; m<r; m++) {
					d = max(d, dp[l][m] + dp[m+1][r]);
				}

				// insert
				int p = l;
				int q = r;
				while (s[l] == s[p+1] && p+1 <= r)
					p++;

				while (s[r] == s[q-1] && q-1 >= l)
					q--;

				if (s[l] == s[r]) {
					for (int x=l+1; x<=r-1; x++) {
						for (int y=x; y<=r-1; y++) {
							if (x <= p+1 && y >= q-1)
								d = max(d, a[x-l+r-y] + dp[x][y]);
						}
					}
				}

				if (p == r)
					d = max(d, a[r-l+1]);
			}
		}
	}

	cout << dp[1][n] << '\n';
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

string s;
int n;
ll dp[105][105], a[105];

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

	cin >> n >> s;
	for (int i=1; i<=n; i++)
		cin >> a[i];
	s = string(" ") + s + string(" ");

	for (int l=n; l>=1; l--) {
		for (int r=l; r<=n; r++) {
			ll& d = dp[l][r];
			if (l == r) {
				d = a[1];
			} else {
				// split?
				for (int m=l; m<r; m++) {
					d = max(d, dp[l][m] + dp[m+1][r]);
				}

				// insert
				int p = l;
				int q = r;
				while (s[l] == s[p+1] && p+1 <= r)
					p++;

				while (s[r] == s[q-1] && q-1 >= l)
					q--;

				for (int x=l+1; x<=r-1; x++) {
					for (int y=x; y<=r-1; y++) {
						if (x <= p+1 && y >= q-1)
							d = max(d, a[x-l+r-y] + dp[x][y]);
					}
				}
			}
		}
	}

	cout << dp[1][n] << '\n';
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

string s;
int n;
ll dp[105][105], a[105];

ll inner0[105][105], inner1[105][105];

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

	cin >> n >> s;
	for (int i=1; i<=n; i++)
		cin >> a[i];
	s = string(" ") + s + string(" ");

	for (int l=n; l>=1; l--) {

		memset(inner0, 128, sizeof(inner0));
		memset(inner1, 128, sizeof(inner1));

		inner0[l-1][0] = inner1[l-1][0] = 0;

		for (int i=l; i<=n; i++) {
			// mogu da samo uzmem ovo ako je kec
			if (s[i] == '1')
				for (int x=1; x<=i-l+1; x++)
					inner1[i][x] = max(inner1[i][x], inner1[i-1][x-1]);
			// spoji unazad
			for (int x=0; x<=i-l+1; x++)
				for (int j=i; j>=l; j--)
					inner1[i][x] = max(inner1[i][x], inner1[j-1][x] + dp[j][i]);
		}

		for (int i=l; i<=n; i++) {
			// mogu da samo uzmem ovo ako je kec
			if (s[i] == '0')
				for (int x=1; x<=i-l+1; x++)
					inner0[i][x] = max(inner0[i][x], inner0[i-1][x-1]);
			// spoji unazad
			for (int x=0; x<=i-l+1; x++)
				for (int j=i; j>=l; j--)
					inner0[i][x] = max(inner0[i][x], inner0[j-1][x] + dp[j][i]);
		}

		for (int r=l; r<=n; r++) {
			for (int x=0; x<=r-l+1; x++) {
				dp[l][r] = max(dp[l][r], inner0[r][x] + a[x]);
				dp[l][r] = max(dp[l][r], inner1[r][x] + a[x]);
			}
		}
	}
	cout << dp[1][n] << '\n';
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

string s;
int n;
int dp[105][105], a[105];

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

	cin >> n >> s;
	for (int i=1; i<=n; i++)
		cin >> a[i];
	s = string(" ") + s + string(" ");

	for (int l=n; l>=1; l--) {
		for (int r=l; r<=n; r++) {
			int& d = dp[l][r];
			if (l == r) {
				d = a[1];
			} else {
				// split?
				for (int m=l; m<r; m++) {
					d = max(d, dp[l][m] + dp[m+1][r]);
				}

				// insert
				int p = l;
				int q = r;
				while (s[l] == s[p+1] && p+1 <= r)
					p++;

				while (s[r] == s[q-1] && q-1 >= l)
					q--;

				for (int x=l+1; x<=r-1; x++) {
					for (int y=x; y<=r-1; y++) {
						if (x <= p+1 && y >= q-1)
							d = max(d, a[x-l+r-y] + dp[x][y]);
					}
				}
			}
		}
	}

	cout << dp[1][n] << '\n';
}


#include <iostream>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <string>
#include <string.h>
#include <set>
#include <queue>
#include <map>
#include <stack>
#include <functional>

using namespace std;

const long long INF = (long long)1e18;

const int len = 110;

long long dp[110][110][110][2];
long long dp2[110][110];
long long a[110];
string s;

long long solve(int i, int j, int k, int c);

long long solve(int i, int j) {
	if (i == j) {
		return a[0];
	}
	if (dp2[i][j] == -1) {
		dp2[i][j] = -INF;
		for (int k = 0; k <= (j - i); k++) {
			dp2[i][j] = max(dp2[i][j], a[k] + solve(i + 1, j, k, s[i] - '0'));
		}
	}
	return dp2[i][j];
}

long long solve(int i, int j, int k, int c) {
	if (k == 0) {
		return solve(i, j);
	}
	if (k > j - i + 1) {
		return -INF;
	}
	if (i == j) {
		if (s[i] - '0' == c) {
			return 0;
		}
		else return -INF;
	}
	if (dp[i][j][k][c] == -1) {
		if (s[i] - '0' == c) {
			dp[i][j][k][c] = solve(i + 1, j, k - 1, c);
		}
		else dp[i][j][k][c] = -INF;
		for (int l = i; l <= j; l++) {
			dp[i][j][k][c] = max(dp[i][j][k][c], solve(i, l) + solve(l + 1, j, k, c));
		}
	}
	return dp[i][j][k][c];
}

int main() {
	int n;
	cin >> n;
	cin >> s;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			dp2[i][j] = -1;
			for (int k = 0; k < n; k++) {
				dp[i][j][k][0] = -1;
				dp[i][j][k][1] = -1;
			}
		}
	}

	cout << solve(0, n - 1) << endl;

	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <vector>
#include <functional>
#include <numeric>
#include <complex>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <assert.h>
#include <sstream>
#include <string>

#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define X first
#define Y second
#define pb(x) push_back(x)
#define FOR(k, n) for (int i = k; i < n; i++)
#define debug printf("Executed ");
#define debug(x) printf("x = %d\n", x);
#define debug2(x, y) printf("x = %d, y = %d\n", x, y);
#define debug3(x, y, z) printf("x = %d, y = %d, z = %d\n", x, y, z);
#define debug4(x, y, z, t) printf("x = %d, y = %d, z = %d, t = %d\n", x, y, z, t);

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;
typedef complex<double> cd;

const int INF = 1e9;
const long long LINF = 1e18;
const double PI = acos(-1);

// Solution

const int MAXN = 103;

ll n, A[MAXN], DP[MAXN][MAXN][MAXN];
char buffer[MAXN];

ll dp(int s, int e, int p) {
    if (DP[s][e][p] != -1) {
        return DP[s][e][p];
    }

    if (s > e) {
        return 0;
    }

    if (s == e) {
        return A[p - 1];
    }

    DP[s][e][p] = A[p - 1] + dp(s + 1, e, 1);

    for (int i = s + 1; i <= e; i++) {
        if (buffer[s] == buffer[i]) {
            DP[s][e][p] = max(DP[s][e][p], dp(s + 1, i - 1, 1) + dp(i, e, p + 1));
        }
    }

    return DP[s][e][p];
}

int main() {
    scanf("%I64d", &n);

    scanf(" %s", buffer);

    for (int i = 0; i < n; i++) {
        scanf("%d", &A[i]);
    }

    for (int i = 0; i < MAXN; i++) {
        for (int j = 0; j < MAXN; j++) {
            for (int k = 0; k < MAXN; k++) {
                DP[i][j][k] = -1;
            }
        }
    }

    printf("%I64d\n", dp(0, n - 1, 1));

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <string>
#include <stdlib.h>
#include <fstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <iterator>
#include <iomanip>
#include <climits>
#include <numeric>
#include <cstring>
using namespace std;
#define ll long long int

const int N = 102;

vector<ll> a;
ll ans[N][N], dp[2][N][N][N];
string s;

ll d(int c, int l, int r, int cnt);

ll make_ans(int l, int r){
    if(l >= r) return 0;

    if(ans[l][r] != -1) return ans[l][r];

    ans[l][r] = 0;

    for(int i = 1; i <= r - l; ++i){
        ans[l][r] = max(ans[l][r], d(0, l, r, i) + a[i - 1]);
        ans[l][r] = max(ans[l][r], d(1, l, r, i) + a[i - 1]);
    }

    return ans[l][r];
}

ll d(int c, int l, int r, int cnt){
    if(!cnt) return make_ans(l, r);

    if(dp[c][l][r][cnt] != -1) return dp[c][l][r][cnt];

    dp[c][l][r][cnt] = -1e18;

    for(int i = l; i < r; ++i){
        if(s[i] - '0' == c){
            dp[c][l][r][cnt] = max(dp[c][l][r][cnt], make_ans(l, i) + d(c, i + 1, r, cnt - 1));
        }
    }

    return dp[c][l][r][cnt];
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n >> s;

    a.resize(n);

    for(int i = 0; i < n; ++i) cin >> a[i];

    memset(dp, -1, sizeof dp);
	memset(ans, -1, sizeof ans);

    cout << make_ans(0, n);
}


#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#define max(a, b) ((a) > (b) ? (a) : (b))

typedef long long ll;
int n;
int a[100 + 10];
char s[100 + 10];
ll f[100 + 10][100 + 10][100 + 10];
ll dfs(const int &l, const int &r, const int &k);

int main() {
	scanf("%d%s", &n, s);
	for (int i = 0; i < n; ++i)
		scanf("%d", &a[i]);
	printf("%I64d\n", dfs(0, n - 1, 0));
	return 0;
}

ll dfs(const int &l, const int &r, const int &k) {
	if (l > r)
		return 0;
	else if (f[l][r][k])
		return f[l][r][k];
	ll ret = a[k] + dfs(l + 1, r, 0);
	for (int i = l + 1; i <= r; ++i)
		if (s[i] == s[l])
			ret = max(ret, dfs(l + 1, i - 1, 0) + dfs(i, r, k + 1));
	return f[l][r][k] = ret;
}