Problem:
クッキーゲーム
N
頂点の無向木があり，各頂点には 1 から
N
までの番号が付けられている．また，各頂点には，1 枚または 2 枚のクッキーが置かれている．
あなたは，この木を使ってゲームを行うことにした．はじめに，あなたは木の頂点を 1 つ選び，その頂点に駒を 1 つ置く．その後，次の行動を，ゲームが終わるまで繰り返す．
現在駒が置かれている頂点にあるクッキーを，1 枚だけ食べる．さらに，現在駒が置かれている頂点に隣接する頂点を 1 つ選び，その頂点に駒を移動させる．移動先の頂点にクッキーが 1 枚も置かれていない場合，その時点でゲームは終了となる．
あなたが最適に行動したとき，ゲーム中，最大で何枚のクッキーを食べることができるだろうか．
Input
入力は 50 個以下のデータセットからなる． 各データセットは次の形式で表される．
N
x
1
x
2
...x
N
p
1
p
2
…
p
N-1
1 行目には，木の頂点数
N
(2 ≤ N ≤ 10
5
)
が与えられる．2 行目は
1
または
2
のみからなる
N
文字の文字列が与えられる．このうち
i
番目の文字
x
i
は，はじめに頂点
i
に置かれているクッキーの枚数を表す．3 行目からの
N-1
行には，木の頂点の隣接情報が与えられる．このうち
j
行目に与えられる整数
p
j
(1 ≤ p
j
≤ j)
は，頂点
j+1
と 頂点
p
j
が隣接していることを表す．
入力の終わりは 1 つのゼロからなる行で表される．
Output
各データセットに対し，あなたがゲーム中に食べることのできるクッキーの枚数の最大値を，1 行に出力せよ．
Sample Input
2
11
1
5
12121
1
2
3
4
8
12112211
1
2
1
3
2
5
6
5
12122
1
2
3
4
0
Output for the Sample Input
2
7
11
8

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> A(N);
    {
        string s;
        cin >> s;
        rep(i,0,N) A[i] = s[i] - '0', A[i] *= 2;
    }
    vector<vector<int>> Child(N);
    rep(i,1,N) {
        int p;
        cin >> p;
        p--;
        Child[p].push_back(i);
    }
    vector DP(N, vector(5, vector<int>(3, -inf)));
    int ANS = 0;
    rrep(x,0,N) {
        DP[x][0][0] = 0;
        for (auto y : Child[x]) {
            auto Cur = DP[x];
            rep(edge,1,4) {
                rep(degx, 0, A[x]-edge+1) {
                    rep(degy, 0, A[y]-edge+1) {
                        if (degy % 2 != edge % 2) continue;
                        rep(endx,0,3) {
                            rep(endy,0,3) {
                                if (endx + endy > 2) break;
                                chmax(DP[x][degx+edge][endx+endy], Cur[degx][endx] + DP[y][degy][endy] + edge);
                            }
                        }
                    }
                }
            }
        }
        rep(deg,0,A[x]) {
            rep(end,0,2) {
                chmax(DP[x][deg+1][end+1], DP[x][deg][end] + 1);
            }
        }
        chmax(ANS, DP[x][2][2]);
        if (A[x] == 4) chmax(ANS, DP[x][4][2]);
    }
    cout << ANS-1 << endl;
}
}
accuracy: 1
time_ms: 560
memory_kb: 39312
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
template<const long long int mod=998244353>
struct modint{
  using mint=modint<mod>;
  long long int x;
  modint(long long int _x=0):x(_x%mod){if(x<0)x+=mod;}
  long long int val(){return x;}
  mint&operator=(const mint&a){x=a.x;return *this;}
  mint&operator+=(const mint&a){x+=a.x;if(x>=mod)x-=mod;return *this;}
  mint&operator-=(const mint&a){x-=a.x;if(x<0)x+=mod;return *this;}
  mint&operator*=(const mint&a){x*=a.x;x%=mod;return *this;}
  friend mint operator+(const mint&a,const mint&b){return mint(a)+=b;}
  friend mint operator-(const mint&a,const mint&b){return mint(a)-=b;}
  friend mint operator*(const mint&a,const mint&b){return mint(a)*=b;}
  mint operator-()const{return mint(0)-*this;}
  mint pow(long long int n){
    if(!n)return 1;
    mint a=1;
    mint _x=x;
    while(n){
      if(n&1)a*=_x;
      _x=_x*_x;n>>=1;
    }
    return a;
  }
  mint inv(){return pow(mod-2);}
  mint&operator/=(mint&a){return *this*=a.inv();}
  friend mint operator/(const mint&a,mint b){return mint(a)/=b;}
};
using mint=modint<998244353>;
int main(){
    while(1){
        int N;cin>>N;
        if(!N)return 0;
        string S;cin>>S;
        vi P(N);
        FOR(i,1,N){cin>>P[i];P[i]--;}
        vvi E(N);
        FOR(i,1,N)E[P[i]].emplace_back(i);
        vi DP(N,1),EP(N,1),FP(N,-1e18),GP(N,-1e18);
        ll ans=1;
        function<void(ll)>dfs=[&](ll v){
            if(!sz(E[v]))return;
            for(auto u:E[v])dfs(u);
            //EP
            for(auto u:E[v])chmax(EP[v],max(FP[u],EP[u])+1);
            //DP
            DP[v]=EP[v];
            for(auto u:E[v])if(S[u]=='2')chmax(DP[v],DP[u]+2);
            if(sz(E[v])>1){
                vi T;
                for(auto u:E[v])T.emplace_back(max(EP[u],FP[u]));
                sort(ALL(T));
                reverse(ALL(T));
                chmax(DP[v],T[0]+T[1]+1);
            }
            if(S[v]=='2'){
                //GP
                GP[v]=1;
                for(auto u:E[v])chmax(GP[v],GP[u]+1);
                //FP
                FP[v]=2*GP[v]+1;
                for(auto u:E[v])if(S[u]=='2')chmax(FP[v],EP[u]+3);
                if(sz(E[v])>1){
                    vi F;
                    for(auto u:E[v])F.emplace_back(max(EP[u],FP[u]));
                    vi F1(sz(F)+1,-1e18),F2(sz(F)+1,-1e18);
                    REP(i,sz(F))F1[i+1]=max(F1[i],F[i]);
                    RREP(i,sz(F))F2[i]=max(F2[i+1],F[i]);
                    REP(i,sz(E[v])){
                        ll u=E[v][i];
                        chmax(FP[v],max(F1[i],F2[i+1])+3);
                        if(GP[u]>=0)chmax(FP[v],max(F1[i],F2[i+1])+2*GP[u]+3);
                    }
                }
            }
        };
        dfs(0);
        REP(i,N){
            chmax(ans,DP[i]);
            chmax(ans,EP[i]);
            chmax(ans,FP[i]);
        }
        //cout<<DP<<endl<<EP<<endl<<FP<<endl<<GP<<endl;
        REP(v,N)if(S[v]=='2'&&sz(E[v])>1){
            set<pi>St;
            for(auto u:E[v])St.insert(pi(max(1LL,2*GP[u]+3),u));
            for(auto u:E[v])if(S[u]=='2'){
                St.erase(pi(max(1LL,2*GP[u]+3),u));
                chmax(ans,DP[u]+3+(*prev(St.end())).F);
                St.insert(pi(max(1LL,2*GP[u]+3),u));
            }
            if(sz(E[v])>2){
                set<pi>st;
                for(auto u:E[v])st.insert(pi(max(EP[u],FP[u]),u));
                for(auto u:E[v]){
                    st.erase(pi(max(EP[u],FP[u]),u));
                    auto p=*prev(st.end()),q=*prev(prev(st.end()));
                    chmax(ans,max(1LL,2*GP[u]+3)+p.F+q.F);
                    st.insert(pi(max(FP[u],EP[u]),u));
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 25376
final_rank: 3

code_snippet: // C++ includes used for precompiling -*- C++ -*-
// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.
/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */
// 17.4.1.2 Headers
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>

#endif

using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
constexpr int INF = 1000000000;
constexpr int64_t llINF = 3000000000000000000;
constexpr double eps = 1e-10;
const double pi = acos(-1);
struct linear_sieve {
    vector<int> least_factor, prime_list;
    linear_sieve(int n) : least_factor(n + 1, 0) {
        for (int i = 2; i <= n; i++) {
            if (least_factor[i] == 0) {
                least_factor[i] = i;
                prime_list.push_back(i);
            }
            for (int p : prime_list) {
                if (ll(i) * p > n || p > least_factor[i]) break;
                least_factor[i * p] = p;
            }
        }
    }
};
ll extgcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
ll modpow(ll a, ll b, ll m) {
    ll res = 1;
    while (b) {
        if (b & 1) {
            res *= a;
            res %= m;
        }
        a *= a;
        a %= m;
        b >>= 1;
    }
    return res;
}
template <int modulo>
struct modint {
    int x;
    modint() : x(0) {}
    modint(int64_t y) : x(y >= 0 ? y % modulo : (modulo - (-y) % modulo) % modulo) {}
    modint &operator+=(const modint &p) {
        if ((x += p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator-=(const modint &p) {
        if ((x += modulo - p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator*=(const modint &p) {
        x = (int)(1LL * x * p.x % modulo);
        return *this;
    }
    modint &operator/=(const modint &p) {
        *this *= p.inv();
        return *this;
    }
    modint operator-() const { return modint(-x); }
    modint operator+(const modint &p) const { return modint(*this) += p; }
    modint operator-(const modint &p) const { return modint(*this) -= p; }
    modint operator*(const modint &p) const { return modint(*this) *= p; }
    modint operator/(const modint &p) const { return modint(*this) /= p; }
    bool operator==(const modint &p) const { return x == p.x; }
    bool operator!=(const modint &p) const { return x != p.x; }
    modint inv() const {
        int a = x, b = modulo, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }
    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const modint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, modint &a) {
        int64_t t;
        is >> t;
        a = modint<modulo>(t);
        return (is);
    }
    int val() const { return x; }
    static constexpr int mod() { return modulo; }
    static constexpr int half() { return (modulo + 1) >> 1; }
};
template <typename T>
struct Binomial {
    vector<T> inv, fact, factinv;
    Binomial(int n) {
        inv.resize(n + 1);
        fact.resize(n + 1);
        factinv.resize(n + 1);
        inv[0] = fact[0] = factinv[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
        factinv[n] = fact[n].inv();
        inv[n] = fact[n - 1] * factinv[n];
        for (int i = n - 1; i >= 1; i--) {
            factinv[i] = factinv[i + 1] * (i + 1);
            inv[i] = fact[i - 1] * factinv[i];
        }
    }
    T C(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r] * factinv[r];
    }
    T P(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r];
    }
    T H(int n, int r) {
        if (n == 0 && r == 0) return 1;
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : C(n + r - 1, r);
    }
};
template <class T>
struct Matrix {
    int n;
    vector<vector<T>> m;
    Matrix() : Matrix(0) {}
    Matrix(int x) : Matrix(vector<vector<T>>(x, vector<T>(x, 0))) {}
    Matrix(const vector<vector<T>> &a) {
        n = a.size();
        m = a;
    }
    vector<T> &operator[](int i) { return m[i]; }
    const vector<T> &operator[](int i) const { return m[i]; }
    static Matrix identity(int x) {
        Matrix res(x);
        for (int i = 0; i < x; i++) res[i][i] = 1;
        return res;
    }
    Matrix operator+(const Matrix &a) const {
        Matrix x = (*this);
        return x += a;
    }
    Matrix operator*(const Matrix &a) const {
        Matrix x = (*this);
        return x *= a;
    }
    Matrix &operator+=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                res[i][j] = m[i][j] + a[i][j];
            }
        }
        m = res.m;
        return *this;
    }
    Matrix &operator*=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    res[i][j] += m[i][k] * a[k][j];
                }
            }
        }
        m = res.m;
        return *this;
    }
    Matrix pow(ll b) const {
        Matrix x = *this, res = identity(n);
        while (b) {
            if (b & 1) {
                res *= x;
            }
            x *= x;
            b >>= 1;
        }
        return res;
    }
};
template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int siz = 1;
    vector<S> dat;
    segtree(int n) : segtree(vector<S>(n, e())) {}
    segtree(const vector<S> &a) {
        while (siz < a.size()) siz <<= 1;
        dat = vector<S>(siz << 1, e());
        for (int i = 0; i < a.size(); i++) dat[siz + i] = a[i];
        for (int i = siz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void set(int p, S x) {
        p += siz;
        dat[p] = x;
        while (p > 0) {
            p >>= 1;
            dat[p] = op(dat[2 * p], dat[2 * p + 1]);
        }
    }
    void add(int p, S x) { set(p, get(p) + x); }
    S get(int p) { return dat[p + siz]; }
    S prod(int l, int r) {
        S vl = e(), vr = e();
        l += siz, r += siz;
        while (l < r) {
            if (l & 1) vl = op(vl, dat[l++]);
            if (r & 1) vr = op(dat[--r], vr);
            l >>= 1, r >>= 1;
        }
        return op(vl, vr);
    }
    S all_prod() { return dat[1]; }
};

template <class T>
struct BIT {
    // 1-indexed
    int n, beki = 1;
    vector<T> bit;
    BIT(int x) {
        bit.resize(x + 1, 0);
        n = x;
        while (beki * 2 <= n) beki *= 2;
    }
    T sum(int i) {
        T res = 0;
        while (i > 0) {
            res += bit[i];
            i -= i & -i;
        }
        return res;
    }
    T sum(int l, int r) {
        //[l,r]
        return sum(r) - (l == 0 ? 0 : sum(l - 1));
    }
    void add(int i, T x) {
        while (i <= n) {
            bit[i] += x;
            i += i & -i;
        }
    }
    int lowerbound(T w) {
        if (w <= 0) return 0;
        int x = 0;
        for (int k = beki; k > 0; k >>= 1) {
            if (x + k <= n && bit[x + k] < w) {
                w -= bit[x + k];
                x += k;
            }
        }
        return x + 1;
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct sparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    sparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            for (int j = 0; j + (1 << i) <= (1 << len); j++) {
                table[i][j] = op(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
            }
        }
        logtable.resize(v.size() + 1);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        assert(l <= r);
        if (l == r) return e();
        int len = logtable[r - l];
        return op(table[len][l], table[len][r - (1 << len)]);
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct disjointsparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    disjointsparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len, e()));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            int shift = 1 << i;
            for (int j = 0; j < (int)v.size(); j += shift << 1) {
                int t = min(j + shift, (int)v.size());
                table[i][t - 1] = v[t - 1];
                for (int k = t - 2; k >= j; k--) table[i][k] = op(v[k], table[i][k + 1]);
                if (v.size() <= t) break;
                table[i][t] = v[t];
                int r = min(t + shift, (int)v.size());
                for (int k = t + 1; k < r; k++) table[i][k] = op(table[i][k - 1], v[k]);
            }
        }
        logtable.resize(1 << len);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        if (l == r) return e();
        if (l >= --r) return table[0][l];
        int len = logtable[l ^ r];
        return op(table[len][l], table[len][r]);
    };
};
struct lca_tree {
    int n, size;
    vector<vector<int>> par;
    vector<int> depth;
    lca_tree(vector<vector<int>> g, int root = 0) : n((int)g.size()), size(log2(n) + 2), par(size, vector<int>(n, -1)), depth(vector<int>(n, n)) {
        queue<int> que;
        depth[root] = 0;
        que.push(root);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            for (int i : g[p]) {
                if (depth[i] > depth[p] + 1) {
                    depth[i] = depth[p] + 1;
                    par[0][i] = p;
                    que.push(i);
                }
            }
        }
        for (int k = 0; k < size - 1; k++) {
            for (int i = 0; i < n; i++) {
                if (par[k][i] == -1)
                    par[k + 1][i] = -1;
                else
                    par[k + 1][i] = par[k][par[k][i]];
            }
        }
    }
    int query(int u, int v) {
        if (depth[u] > depth[v]) swap(u, v);
        for (int k = size - 1; k >= 0; k--) {
            if (((depth[v] - depth[u]) >> k) & 1) v = par[k][v];
            if (u == v) return u;
        }
        for (int k = size - 1; k >= 0; k--) {
            if (par[k][u] != par[k][v]) {
                u = par[k][u];
                v = par[k][v];
            }
        }
        return par[0][u];
    }
    int dist(int u, int v) {
        int l = query(u, v);
        return depth[u] + depth[v] - 2 * depth[l];
    }
};
struct UnionFind {
    vector<int> par, siz, es;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        es.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
            es[i] = 0;
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) {
            es[x]++;
            return false;
        }
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];
        es[x] += es[y] + 1;
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
    int edges(int x) { return es[find(x)]; }
};
struct Mo {
    int n;
    vector<pair<int, int>> lr;

    explicit Mo(int n) : n(n) {}

    void add(int l, int r) { /* [l, r) */
        lr.emplace_back(l, r);
    }

    template <typename AL, typename AR, typename EL, typename ER, typename O>
    void build(const AL &add_left, const AR &add_right, const EL &erase_left, const ER &erase_right, const O &out) {
        int q = (int)lr.size();
        int bs = n / min<int>(n, sqrt(q));
        vector<int> ord(q);
        iota(begin(ord), end(ord), 0);
        sort(begin(ord), end(ord), [&](int a, int b) {
            int ablock = lr[a].first / bs, bblock = lr[b].first / bs;
            if (ablock != bblock) return ablock < bblock;
            return (ablock & 1) ? lr[a].second > lr[b].second : lr[a].second < lr[b].second;
        });
        int l = 0, r = 0;
        for (auto idx : ord) {
            while (l > lr[idx].first) add_left(--l);
            while (r < lr[idx].second) add_right(r++);
            while (l < lr[idx].first) erase_left(l++);
            while (r > lr[idx].second) erase_right(--r);
            out(idx);
        }
    }

    template <typename A, typename E, typename O>
    void build(const A &add, const E &erase, const O &out) {
        build(add, add, erase, erase, out);
    }
};
template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
    int _n, sz = 1;
    vector<S> dat;
    vector<F> lazy;
    lazy_segtree(vector<S> a) : _n(int(a.size())) {
        while (sz < _n) sz <<= 1;
        dat.resize(sz * 2, e());
        lazy.resize(sz * 2, id());
        rep(i, _n) dat[sz + i] = a[i];
        for (int i = sz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void eval(int k) {
        dat[k] = mapping(lazy[k], dat[k]);
        if (k < sz) {
            lazy[k * 2] = composition(lazy[k], lazy[k * 2]);
            lazy[k * 2 + 1] = composition(lazy[k], lazy[k * 2 + 1]);
        }
        lazy[k] = id();
    }
    void apply(int a, int b, F f, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = composition(f, lazy[k]);
            eval(k);
            return;
        }
        int m = (l + r) >> 1;
        apply(a, b, f, 2 * k, l, m);
        apply(a, b, f, 2 * k + 1, m, r);
        dat[k] = op(dat[2 * k], dat[2 * k + 1]);
    }
    S prod(int a, int b, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return e();
        if (a <= l && r <= b) return dat[k];
        int m = (l + r) >> 1;
        S vl = prod(a, b, 2 * k, l, m);
        S vr = prod(a, b, 2 * k + 1, m, r);
        return op(vl, vr);
    }
};

template <class S, S (*op)(S, S), S (*e)()>
struct dual_segtree {
    int sz = 1, log = 0;
    vector<S> lz;
    dual_segtree(vector<S> a) {
        int n = a.size();
        while (sz < n) {
            sz <<= 1;
            log++;
        }
        lz.assign(sz << 1, e());
        for (int i = 0; i < n; i++) lz[i + sz] = a[i];
    }
    void push(int k) {
        int b = __builtin_ctz(k);
        for (int d = log; d > b; d--) {
            lz[k >> d << 1] = op(lz[k >> d << 1], lz[k >> d]);
            lz[k >> d << 1 | 1] = op(lz[k >> d << 1 | 1], lz[k >> d]);
            lz[k >> d] = e();
        }
    }
    void apply(int l, int r, S x) {
        l += sz, r += sz;
        push(l);
        push(r);
        while (l < r) {
            if (l & 1) {
                lz[l] = op(lz[l], x);
                l++;
            }
            if (r & 1) {
                r--;
                lz[r] = op(lz[r], x);
            }
            l >>= 1, r >>= 1;
        }
    }
    S get(int k) {
        k += sz;
        S res = e();
        while (k) {
            res = op(res, lz[k]);
            k >>= 1;
        }
        return res;
    }
};
ll modinv(int x, int modulo) {
    int a = x, b = modulo, u = 1, v = 0, t;
    while (b > 0) {
        t = a / b;
        swap(a -= t * b, b);
        swap(u -= t * v, v);
    }
    return (u >= 0 ? u % modulo : (modulo - (-u) % modulo) % modulo);
}
struct auxiliary_tree : lca_tree {
    vector<int> in;
    vector<vector<int>> G;
    auxiliary_tree(vector<vector<int>> &g) : lca_tree(g), in((int)g.size()), G((int)g.size()) {
        int t = 0;
        dfs(0, -1, t, g);
    }
    void dfs(int v, int p, int &t, vector<vector<int>> &g) {
        in[v] = t++;
        for (auto u : g[v]) {
            if (u != p) dfs(u, v, t, g);
        }
    }
    using lca_tree::depth;
    pair<int, vector<int>> query(vector<int> vs, bool decending = false) {
        // decending: only parent to child
        assert(!vs.empty());
        sort(vs.begin(), vs.end(), [&](int a, int b) { return in[a] < in[b]; });
        int m = vs.size();
        stack<int> st;
        st.push(vs[0]);
        for (int i = 0; i < m - 1; i++) {
            int w = lca_tree::query(vs[i], vs[i + 1]);
            if (w != vs[i]) {
                int l = st.top();
                st.pop();
                while (!st.empty() && depth[w] < depth[st.top()]) {
                    if (!decending) G[l].push_back(st.top());
                    G[st.top()].push_back(l);
                    l = st.top();
                    st.pop();
                }
                if (st.empty() || st.top() != w) {
                    st.push(w);
                    vs.push_back(w);
                }
                if (!decending) G[l].push_back(w);
                G[w].push_back(l);
            }
            st.push(vs[i + 1]);
        }
        while (st.size() > 1) {
            int x = st.top();
            st.pop();
            if (!decending) G[x].push_back(st.top());
            G[st.top()].push_back(x);
        }
        // {root,vertex_list}
        return make_pair(st.top(), vs);
    }
    void clear(vector<int> vs) {
        for (int v : vs) G[v].clear();
    }
};
struct LowLink {
    vector<vector<int>> g;
    vector<int> ord, low, out;
    vector<bool> used;
    vector<pair<int, int>> bridge;
    vector<pair<int, int>> articulation;
    int unions;
    LowLink(vector<vector<int>> g) : g(g) {
        int n = (int)g.size();
        ord.resize(n);
        low.resize(n);
        out.resize(n);
        used.resize(n);
        unions = 0;
        int t = 0;
        for (int i = 0; i < n; i++) {
            if (!used[i]) {
                dfs(i, t, -1);
                unions++;
            }
        }
    }
    void dfs(int v, int &t, int par) {
        used[v] = true;
        ord[v] = t++, low[v] = ord[v];
        int cnt = 0;
        bool par_back = false;
        for (int to : g[v]) {
            if (!used[to]) {
                dfs(to, t, v);
                low[v] = min(low[v], low[to]);
                if (ord[v] < low[to]) bridge.push_back(minmax(v, to));
                if (ord[v] <= low[to]) cnt++;
            } else if (to != par || par_back) {
                low[v] = min(low[v], ord[to]);
            } else
                par_back = true;
        }
        if (par != -1) cnt++;
        if (cnt >= 2) articulation.push_back({v, cnt});
        out[v] = t;
    }
};
struct S {
    int x, y, z, w;
    // 1&gone 1&back 2&gone 2&back
};
S dp[200010], dp2[200010];
string T;
vector<int> g[200010];
S merge(S a, S b) { return {max(a.x, b.x), max(a.y, b.y), max({a.z, b.z, a.x + b.y, a.y + b.x}), max(a.w, b.w)}; }
S fe(S x, int v) { return x; }
S fv(S x, int ch) {
    if (T[ch] == '1') {
        return {max({1, x.x + 1, x.y + 1}), 1, -INF, 1};
    } else {
        return {max({x.x + 1, x.y + 2, x.z + 2, x.w + 2}), max(1, x.y + 2), -INF, max(2, x.x + 2)};
    }
}
S e() { return S{-INF, -INF, -INF, -INF}; }
void dfs1(int v, int p = -1) {
    dp[v] = e();
    for (int u : g[v]) {
        if (u != p) {
            dfs1(u, v);
            dp[v] = merge(dp[v], dp2[u]);
        }
    }
    dp2[v] = fe(fv(dp[v], v), v);
}
void dfs2(int v, int par = -1, S dp_par = e()) {
    int k = g[v].size();
    vector<S> c1(k + 1), c2(k + 1);
    // c1[i]:fold[0,i)
    // c2[i]:fold[i,k)
    c1[0] = c2[k] = e();
    rep(i, k) {
        int u = g[v][i];
        if (u == par) {
            S tmp = fe(fv(dp_par, par), par);
            c1[i + 1] = c2[i] = tmp;
            dp[v] = merge(dp[v], tmp);
        } else {
            c1[i + 1] = c2[i] = dp2[u];
        }
    }
    rep(i, k) c1[i + 1] = merge(c1[i + 1], c1[i]);
    for (int i = k - 1; i >= 0; i--) c2[i] = merge(c2[i], c2[i + 1]);
    rep(i, k) {
        int u = g[v][i];
        if (u != par) {
            dfs2(u, v, merge(c1[i], c2[i + 1]));
        }
    }
    dp[v] = fv(dp[v], v);
}
void solve(int n) {
    cin >> T;
    for (int i = 1; i < n; i++) {
        int j;
        cin >> j;
        j--;
        g[i].push_back(j);
        g[j].push_back(i);
    }
    dfs1(0);
    dfs2(0);
    int ans = 0;
    rep(i, n) chmax(ans, max({dp[i].x, dp[i].y, dp[i].z}));
    cout << ans << endl;
    rep(i, n) {
        g[i].clear();
        dp[i] = dp2[i] = e();
    }
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int x;
    int n, m, k, d, b;
    string s;
    while (cin >> n) {
        if (n == 0) break;
        solve(n);
    }
}
accuracy: 1
time_ms: 170
memory_kb: 43284
final_rank: 4

code_snippet: // C++ includes used for precompiling -*- C++ -*-
// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.
/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */
// 17.4.1.2 Headers
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>

#endif

using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
constexpr int INF = 1000000000;
constexpr int64_t llINF = 3000000000000000000;
constexpr double eps = 1e-10;
const double pi = acos(-1);
struct linear_sieve {
    vector<int> least_factor, prime_list;
    linear_sieve(int n) : least_factor(n + 1, 0) {
        for (int i = 2; i <= n; i++) {
            if (least_factor[i] == 0) {
                least_factor[i] = i;
                prime_list.push_back(i);
            }
            for (int p : prime_list) {
                if (ll(i) * p > n || p > least_factor[i]) break;
                least_factor[i * p] = p;
            }
        }
    }
};
ll extgcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
ll modpow(ll a, ll b, ll m) {
    ll res = 1;
    while (b) {
        if (b & 1) {
            res *= a;
            res %= m;
        }
        a *= a;
        a %= m;
        b >>= 1;
    }
    return res;
}
template <int modulo>
struct modint {
    int x;
    modint() : x(0) {}
    modint(int64_t y) : x(y >= 0 ? y % modulo : (modulo - (-y) % modulo) % modulo) {}
    modint &operator+=(const modint &p) {
        if ((x += p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator-=(const modint &p) {
        if ((x += modulo - p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator*=(const modint &p) {
        x = (int)(1LL * x * p.x % modulo);
        return *this;
    }
    modint &operator/=(const modint &p) {
        *this *= p.inv();
        return *this;
    }
    modint operator-() const { return modint(-x); }
    modint operator+(const modint &p) const { return modint(*this) += p; }
    modint operator-(const modint &p) const { return modint(*this) -= p; }
    modint operator*(const modint &p) const { return modint(*this) *= p; }
    modint operator/(const modint &p) const { return modint(*this) /= p; }
    bool operator==(const modint &p) const { return x == p.x; }
    bool operator!=(const modint &p) const { return x != p.x; }
    modint inv() const {
        int a = x, b = modulo, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }
    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const modint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, modint &a) {
        int64_t t;
        is >> t;
        a = modint<modulo>(t);
        return (is);
    }
    int val() const { return x; }
    static constexpr int mod() { return modulo; }
    static constexpr int half() { return (modulo + 1) >> 1; }
};
template <typename T>
struct Binomial {
    vector<T> inv, fact, factinv;
    Binomial(int n) {
        inv.resize(n + 1);
        fact.resize(n + 1);
        factinv.resize(n + 1);
        inv[0] = fact[0] = factinv[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
        factinv[n] = fact[n].inv();
        inv[n] = fact[n - 1] * factinv[n];
        for (int i = n - 1; i >= 1; i--) {
            factinv[i] = factinv[i + 1] * (i + 1);
            inv[i] = fact[i - 1] * factinv[i];
        }
    }
    T C(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r] * factinv[r];
    }
    T P(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r];
    }
    T H(int n, int r) {
        if (n == 0 && r == 0) return 1;
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : C(n + r - 1, r);
    }
};
template <class T>
struct Matrix {
    int n;
    vector<vector<T>> m;
    Matrix() : Matrix(0) {}
    Matrix(int x) : Matrix(vector<vector<T>>(x, vector<T>(x, 0))) {}
    Matrix(const vector<vector<T>> &a) {
        n = a.size();
        m = a;
    }
    vector<T> &operator[](int i) { return m[i]; }
    const vector<T> &operator[](int i) const { return m[i]; }
    static Matrix identity(int x) {
        Matrix res(x);
        for (int i = 0; i < x; i++) res[i][i] = 1;
        return res;
    }
    Matrix operator+(const Matrix &a) const {
        Matrix x = (*this);
        return x += a;
    }
    Matrix operator*(const Matrix &a) const {
        Matrix x = (*this);
        return x *= a;
    }
    Matrix &operator+=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                res[i][j] = m[i][j] + a[i][j];
            }
        }
        m = res.m;
        return *this;
    }
    Matrix &operator*=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    res[i][j] += m[i][k] * a[k][j];
                }
            }
        }
        m = res.m;
        return *this;
    }
    Matrix pow(ll b) const {
        Matrix x = *this, res = identity(n);
        while (b) {
            if (b & 1) {
                res *= x;
            }
            x *= x;
            b >>= 1;
        }
        return res;
    }
};
template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int siz = 1;
    vector<S> dat;
    segtree(int n) : segtree(vector<S>(n, e())) {}
    segtree(const vector<S> &a) {
        while (siz < a.size()) siz <<= 1;
        dat = vector<S>(siz << 1, e());
        for (int i = 0; i < a.size(); i++) dat[siz + i] = a[i];
        for (int i = siz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void set(int p, S x) {
        p += siz;
        dat[p] = x;
        while (p > 0) {
            p >>= 1;
            dat[p] = op(dat[2 * p], dat[2 * p + 1]);
        }
    }
    void add(int p, S x) { set(p, get(p) + x); }
    S get(int p) { return dat[p + siz]; }
    S prod(int l, int r) {
        S vl = e(), vr = e();
        l += siz, r += siz;
        while (l < r) {
            if (l & 1) vl = op(vl, dat[l++]);
            if (r & 1) vr = op(dat[--r], vr);
            l >>= 1, r >>= 1;
        }
        return op(vl, vr);
    }
    S all_prod() { return dat[1]; }
};

template <class T>
struct BIT {
    // 1-indexed
    int n, beki = 1;
    vector<T> bit;
    BIT(int x) {
        bit.resize(x + 1, 0);
        n = x;
        while (beki * 2 <= n) beki *= 2;
    }
    T sum(int i) {
        T res = 0;
        while (i > 0) {
            res += bit[i];
            i -= i & -i;
        }
        return res;
    }
    T sum(int l, int r) {
        //[l,r]
        return sum(r) - (l == 0 ? 0 : sum(l - 1));
    }
    void add(int i, T x) {
        while (i <= n) {
            bit[i] += x;
            i += i & -i;
        }
    }
    int lowerbound(T w) {
        if (w <= 0) return 0;
        int x = 0;
        for (int k = beki; k > 0; k >>= 1) {
            if (x + k <= n && bit[x + k] < w) {
                w -= bit[x + k];
                x += k;
            }
        }
        return x + 1;
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct sparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    sparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            for (int j = 0; j + (1 << i) <= (1 << len); j++) {
                table[i][j] = op(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
            }
        }
        logtable.resize(v.size() + 1);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        assert(l <= r);
        if (l == r) return e();
        int len = logtable[r - l];
        return op(table[len][l], table[len][r - (1 << len)]);
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct disjointsparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    disjointsparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len, e()));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            int shift = 1 << i;
            for (int j = 0; j < (int)v.size(); j += shift << 1) {
                int t = min(j + shift, (int)v.size());
                table[i][t - 1] = v[t - 1];
                for (int k = t - 2; k >= j; k--) table[i][k] = op(v[k], table[i][k + 1]);
                if (v.size() <= t) break;
                table[i][t] = v[t];
                int r = min(t + shift, (int)v.size());
                for (int k = t + 1; k < r; k++) table[i][k] = op(table[i][k - 1], v[k]);
            }
        }
        logtable.resize(1 << len);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        if (l == r) return e();
        if (l >= --r) return table[0][l];
        int len = logtable[l ^ r];
        return op(table[len][l], table[len][r]);
    };
};
struct lca_tree {
    int n, size;
    vector<vector<int>> par;
    vector<int> depth;
    lca_tree(vector<vector<int>> g, int root = 0) : n((int)g.size()), size(log2(n) + 2), par(size, vector<int>(n, -1)), depth(vector<int>(n, n)) {
        queue<int> que;
        depth[root] = 0;
        que.push(root);
        while (!que.empty()) {
            int p = que.front();
            que.pop();
            for (int i : g[p]) {
                if (depth[i] > depth[p] + 1) {
                    depth[i] = depth[p] + 1;
                    par[0][i] = p;
                    que.push(i);
                }
            }
        }
        for (int k = 0; k < size - 1; k++) {
            for (int i = 0; i < n; i++) {
                if (par[k][i] == -1)
                    par[k + 1][i] = -1;
                else
                    par[k + 1][i] = par[k][par[k][i]];
            }
        }
    }
    int query(int u, int v) {
        if (depth[u] > depth[v]) swap(u, v);
        for (int k = size - 1; k >= 0; k--) {
            if (((depth[v] - depth[u]) >> k) & 1) v = par[k][v];
            if (u == v) return u;
        }
        for (int k = size - 1; k >= 0; k--) {
            if (par[k][u] != par[k][v]) {
                u = par[k][u];
                v = par[k][v];
            }
        }
        return par[0][u];
    }
    int dist(int u, int v) {
        int l = query(u, v);
        return depth[u] + depth[v] - 2 * depth[l];
    }
};
struct UnionFind {
    vector<int> par, siz, es;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        es.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
            es[i] = 0;
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) {
            es[x]++;
            return false;
        }
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];
        es[x] += es[y] + 1;
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
    int edges(int x) { return es[find(x)]; }
};
struct Mo {
    int n;
    vector<pair<int, int>> lr;

    explicit Mo(int n) : n(n) {}

    void add(int l, int r) { /* [l, r) */
        lr.emplace_back(l, r);
    }

    template <typename AL, typename AR, typename EL, typename ER, typename O>
    void build(const AL &add_left, const AR &add_right, const EL &erase_left, const ER &erase_right, const O &out) {
        int q = (int)lr.size();
        int bs = n / min<int>(n, sqrt(q));
        vector<int> ord(q);
        iota(begin(ord), end(ord), 0);
        sort(begin(ord), end(ord), [&](int a, int b) {
            int ablock = lr[a].first / bs, bblock = lr[b].first / bs;
            if (ablock != bblock) return ablock < bblock;
            return (ablock & 1) ? lr[a].second > lr[b].second : lr[a].second < lr[b].second;
        });
        int l = 0, r = 0;
        for (auto idx : ord) {
            while (l > lr[idx].first) add_left(--l);
            while (r < lr[idx].second) add_right(r++);
            while (l < lr[idx].first) erase_left(l++);
            while (r > lr[idx].second) erase_right(--r);
            out(idx);
        }
    }

    template <typename A, typename E, typename O>
    void build(const A &add, const E &erase, const O &out) {
        build(add, add, erase, erase, out);
    }
};
template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
    int _n, sz = 1;
    vector<S> dat;
    vector<F> lazy;
    lazy_segtree(vector<S> a) : _n(int(a.size())) {
        while (sz < _n) sz <<= 1;
        dat.resize(sz * 2, e());
        lazy.resize(sz * 2, id());
        rep(i, _n) dat[sz + i] = a[i];
        for (int i = sz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void eval(int k) {
        dat[k] = mapping(lazy[k], dat[k]);
        if (k < sz) {
            lazy[k * 2] = composition(lazy[k], lazy[k * 2]);
            lazy[k * 2 + 1] = composition(lazy[k], lazy[k * 2 + 1]);
        }
        lazy[k] = id();
    }
    void apply(int a, int b, F f, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = composition(f, lazy[k]);
            eval(k);
            return;
        }
        int m = (l + r) >> 1;
        apply(a, b, f, 2 * k, l, m);
        apply(a, b, f, 2 * k + 1, m, r);
        dat[k] = op(dat[2 * k], dat[2 * k + 1]);
    }
    S prod(int a, int b, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return e();
        if (a <= l && r <= b) return dat[k];
        int m = (l + r) >> 1;
        S vl = prod(a, b, 2 * k, l, m);
        S vr = prod(a, b, 2 * k + 1, m, r);
        return op(vl, vr);
    }
};

template <class S, S (*op)(S, S), S (*e)()>
struct dual_segtree {
    int sz = 1, log = 0;
    vector<S> lz;
    dual_segtree(vector<S> a) {
        int n = a.size();
        while (sz < n) {
            sz <<= 1;
            log++;
        }
        lz.assign(sz << 1, e());
        for (int i = 0; i < n; i++) lz[i + sz] = a[i];
    }
    void push(int k) {
        int b = __builtin_ctz(k);
        for (int d = log; d > b; d--) {
            lz[k >> d << 1] = op(lz[k >> d << 1], lz[k >> d]);
            lz[k >> d << 1 | 1] = op(lz[k >> d << 1 | 1], lz[k >> d]);
            lz[k >> d] = e();
        }
    }
    void apply(int l, int r, S x) {
        l += sz, r += sz;
        push(l);
        push(r);
        while (l < r) {
            if (l & 1) {
                lz[l] = op(lz[l], x);
                l++;
            }
            if (r & 1) {
                r--;
                lz[r] = op(lz[r], x);
            }
            l >>= 1, r >>= 1;
        }
    }
    S get(int k) {
        k += sz;
        S res = e();
        while (k) {
            res = op(res, lz[k]);
            k >>= 1;
        }
        return res;
    }
};
ll modinv(int x, int modulo) {
    int a = x, b = modulo, u = 1, v = 0, t;
    while (b > 0) {
        t = a / b;
        swap(a -= t * b, b);
        swap(u -= t * v, v);
    }
    return (u >= 0 ? u % modulo : (modulo - (-u) % modulo) % modulo);
}
struct auxiliary_tree : lca_tree {
    vector<int> in;
    vector<vector<int>> G;
    auxiliary_tree(vector<vector<int>> &g) : lca_tree(g), in((int)g.size()), G((int)g.size()) {
        int t = 0;
        dfs(0, -1, t, g);
    }
    void dfs(int v, int p, int &t, vector<vector<int>> &g) {
        in[v] = t++;
        for (auto u : g[v]) {
            if (u != p) dfs(u, v, t, g);
        }
    }
    using lca_tree::depth;
    pair<int, vector<int>> query(vector<int> vs, bool decending = false) {
        // decending: only parent to child
        assert(!vs.empty());
        sort(vs.begin(), vs.end(), [&](int a, int b) { return in[a] < in[b]; });
        int m = vs.size();
        stack<int> st;
        st.push(vs[0]);
        for (int i = 0; i < m - 1; i++) {
            int w = lca_tree::query(vs[i], vs[i + 1]);
            if (w != vs[i]) {
                int l = st.top();
                st.pop();
                while (!st.empty() && depth[w] < depth[st.top()]) {
                    if (!decending) G[l].push_back(st.top());
                    G[st.top()].push_back(l);
                    l = st.top();
                    st.pop();
                }
                if (st.empty() || st.top() != w) {
                    st.push(w);
                    vs.push_back(w);
                }
                if (!decending) G[l].push_back(w);
                G[w].push_back(l);
            }
            st.push(vs[i + 1]);
        }
        while (st.size() > 1) {
            int x = st.top();
            st.pop();
            if (!decending) G[x].push_back(st.top());
            G[st.top()].push_back(x);
        }
        // {root,vertex_list}
        return make_pair(st.top(), vs);
    }
    void clear(vector<int> vs) {
        for (int v : vs) G[v].clear();
    }
};
struct LowLink {
    vector<vector<int>> g;
    vector<int> ord, low, out;
    vector<bool> used;
    vector<pair<int, int>> bridge;
    vector<pair<int, int>> articulation;
    int unions;
    LowLink(vector<vector<int>> g) : g(g) {
        int n = (int)g.size();
        ord.resize(n);
        low.resize(n);
        out.resize(n);
        used.resize(n);
        unions = 0;
        int t = 0;
        for (int i = 0; i < n; i++) {
            if (!used[i]) {
                dfs(i, t, -1);
                unions++;
            }
        }
    }
    void dfs(int v, int &t, int par) {
        used[v] = true;
        ord[v] = t++, low[v] = ord[v];
        int cnt = 0;
        bool par_back = false;
        for (int to : g[v]) {
            if (!used[to]) {
                dfs(to, t, v);
                low[v] = min(low[v], low[to]);
                if (ord[v] < low[to]) bridge.push_back(minmax(v, to));
                if (ord[v] <= low[to]) cnt++;
            } else if (to != par || par_back) {
                low[v] = min(low[v], ord[to]);
            } else
                par_back = true;
        }
        if (par != -1) cnt++;
        if (cnt >= 2) articulation.push_back({v, cnt});
        out[v] = t;
    }
};
struct S {
    int x, y, z, w;
    // 1&gone 1&back 2&gone 2&back
};
S dp[200010], dp2[200010], res[200010];
string T;
vector<int> g[200010];
S merge(S a, S b) { return {max(a.x, b.x), max(a.y, b.y), max({a.z, b.z, a.x + b.y, a.y + b.x}), max(a.w, b.w)}; }
S fe(S x, int v) { return x; }
S fv(S x, int ch) {
    if (T[ch] == '1') {
        return {max({1, x.x + 1, x.y + 1}), 1, -INF, 1};
    } else {
        return {max({x.x + 1, x.y + 2, x.z + 2, x.w + 2}), max(1, x.y + 2), -INF, max(2, x.x + 2)};
    }
}
S e() { return S{-INF, -INF, -INF, -INF}; }
void dfs1(int v, int p = -1) {
    dp[v] = e();
    for (int u : g[v]) {
        if (u != p) {
            dfs1(u, v);
            dp[v] = merge(dp[v], dp2[u]);
        }
    }
    dp2[v] = fe(fv(dp[v], v), v);
}
void dfs2(int v, int par = -1, S dp_par = e()) {
    int k = g[v].size();
    vector<S> c1(k + 1), c2(k + 1);
    // c1[i]:fold[0,i)
    // c2[i]:fold[i,k)
    c1[0] = c2[k] = e();
    rep(i, k) {
        int u = g[v][i];
        if (u == par) {
            S tmp = fe(fv(dp_par, par), par);
            c1[i + 1] = c2[i] = tmp;
            dp[v] = merge(dp[v], tmp);
        } else {
            c1[i + 1] = c2[i] = dp2[u];
        }
    }
    rep(i, k) c1[i + 1] = merge(c1[i + 1], c1[i]);
    for (int i = k - 1; i >= 0; i--) c2[i] = merge(c2[i], c2[i + 1]);
    rep(i, k) {
        int u = g[v][i];
        if (u != par) {
            dfs2(u, v, merge(c1[i], c2[i + 1]));
        }
    }
    dp[v] = fv(dp[v], v);
}
void solve(int n) {
    cin >> T;
    rep(i, n) {
        g[i].clear();
        dp[i] = dp2[i] = e();
    }
    for (int i = 1; i < n; i++) {
        int j;
        cin >> j;
        j--;
        g[i].push_back(j);
        g[j].push_back(i);
    }
    dfs1(0);
    dfs2(0);
    int ans = 0;
    rep(i, n) chmax(ans, max({dp[i].x, dp[i].y, dp[i].z}));
    cout << ans << endl;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int x;
    int n, m, k, d, b;
    string s;
    while (cin >> n) {
        if (n == 0) break;
        solve(n);
    }
}
accuracy: 1
time_ms: 170
memory_kb: 45868
final_rank: 5

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

template <typename key_t, typename sum_t = key_t> struct ReRooting {
    struct Edge {
        int from, to;
        key_t cost;
        sum_t dp, ndp;
    };
    using F = function<sum_t(sum_t, sum_t)>;
    using G = function<sum_t(sum_t, Edge)>;

    vector<vector<Edge>> g;
    const F f;
    const G gg;
    const sum_t id;
    vector<sum_t> subdp, dp;

    void add_edge(int u, int v, const key_t &d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, d, id, id});
    }
    void add_edge(int u, int v, const key_t &d, const key_t &rev_d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, rev_d, id, id});
    }
    void add_directed_edge(int u, int v, const key_t &d) { g[u].emplace_back(Edge{u, v, d, id, id}); }

    ReRooting(int n, const G &g, const F &f, const sum_t &id = sum_t{}) : g(n), f(f), gg(g), id(id), subdp(n, id), dp(n, id) {}
    ReRooting(Graph &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, 1);
    }
    template <typename T>
    ReRooting(Wgraph<T> &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, e.cost);
    }

    void dfs_sub(int x, int p) {
        for(auto &e : g[x]) {
            if(e.to == p) continue;
            dfs_sub(e.to, x);
            e.dp = gg(subdp[e.to], e);
            subdp[x] = f(subdp[x], e.dp);
        }
    }

    stack<tuple<int, int, sum_t>> dfs_st;

    void dfs_all(int x, int p, sum_t top) {
        sum_t now = id;
        for(int i = 0; i < (int)g[x].size(); i++) {
            auto &e = g[x][i];
            e.ndp = now;
            if(e.to == p) e.dp = gg(top, e);
            now = f(now, e.dp);
        }
        dp[x] = now;
        now = id;
        for(int i = (int)g[x].size() - 1; i >= 0; i--) {
            auto &e = g[x][i];
            if(e.to != p) dfs_st.emplace(e.to, x, f(e.ndp, now));
            now = f(now, e.dp);
        }
    }

    vector<sum_t> build() {
        dfs_sub(0, -1);
        dfs_st.emplace(0, -1, id);
        while(!empty(dfs_st)) {
            auto [a, b, c] = dfs_st.top();
            dfs_st.pop();
            dfs_all(a, b, c);
        }
        return dp;
    }
};

int main() {
    while(1) {
        INT(n);
        if(!n) exit(0);
        STR(s);
        vi a;
        for(auto e : s) a.eb(e - '0');
        Graph g(n);
        rep2(i, 1, n - 1) {
            INT(x);
            add(g, i, x - 1);
        }
        constexpr int M = 3;
        struct A {
            pii rev[M];
            pii go[M];
            A() { rep(i, M) rev[i].fi = -inf<int>, go[i].fi = -inf<int>; }
        };

        auto f = [](A p, A q) {
            pii rev[M * 2], go[M * 2];
            rep(i, M) rev[i] = p.rev[i], rev[i + M] = q.rev[i];
            rep(i, M) go[i] = p.go[i], go[i + M] = q.go[i];
            sort(rev, rev + M * 2, greater{}), sort(go, go + M * 2, greater{});
            A res;
            rep(i, M) res.rev[i] = rev[i], res.go[i] = go[i];
            return res;
        };

        auto gg = [&](A p, ReRooting<int, A>::Edge e) {
            if(a[e.to] == 2) {
                A res;
                res.rev[1] = pii(1, e.to + n);
                res.go[1] = pii(1, e.to + n);
                rep(i, M) rep(j, M) {
                    if(p.rev[i].se % n != p.go[j].se % n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    } else if(p.rev[i].se >= n and p.go[j].se >= n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    }
                }
                rep(i, M) rep(j, i) if(p.rev[i].se % n != p.rev[j].se % n) chmax(res.go[0], pii(p.rev[i].fi + p.rev[j].fi + 2, e.to));
                chmax(res.go[1], pii(1 + p.go[0].fi, e.to + n));
                chmax(res.go[1], pii(1 + p.rev[0].fi, e.to + n));
                chmax(res.go[0], pii(2 + p.rev[0].fi, e.to));
                chmax(res.rev[0], pii(2 + p.rev[0].fi, e.to));
                return res;
            } else {
                A res;
                res.rev[0] = pii(1, e.to);
                res.go[0] = pii(max(1, p.go[0].fi + 1), e.to);
                return res;
            }
        };

        ReRooting<int, A> rr(g, gg, f, A());

        auto res = rr.build();

        int ma = 1;
        rep(i, n) {
            if(a[i] == 2) {
                rep(x, M) rep(y, M) {
                    if(res[i].rev[x].se % n != res[i].go[y].se % n)
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    else if(res[i].rev[x].se >= n and res[i].go[y].se >= n) {
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    }
                }
                rep(j, M) {
                    chmax(ma, res[i].go[j].fi + 1);
                    chmax(ma, res[i].rev[j].fi + 2);
                }
            } else {
                rep(j, M) chmax(ma, res[i].go[j].fi + 1);
                rep(j, M) chmax(ma, res[i].rev[j].fi + 1);
            }
        }
        OUT(ma);
    }
}
accuracy: 1
time_ms: 600
memory_kb: 82488
final_rank: 12

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

template <typename key_t, typename sum_t = key_t> struct ReRooting {
    struct Edge {
        int from, to;
        key_t cost;
        sum_t dp, ndp;
    };
    using F = function<sum_t(sum_t, sum_t)>;
    using G = function<sum_t(sum_t, Edge)>;

    vector<vector<Edge>> g;
    const F f;
    const G gg;
    const sum_t id;
    vector<sum_t> subdp, dp;

    void add_edge(int u, int v, const key_t &d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, d, id, id});
    }
    void add_edge(int u, int v, const key_t &d, const key_t &rev_d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, rev_d, id, id});
    }
    void add_directed_edge(int u, int v, const key_t &d) { g[u].emplace_back(Edge{u, v, d, id, id}); }

    ReRooting(int n, const G &g, const F &f, const sum_t &id = sum_t{}) : g(n), f(f), gg(g), id(id), subdp(n, id), dp(n, id) {}
    ReRooting(Graph &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, 1);
    }
    template <typename T>
    ReRooting(Wgraph<T> &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, e.cost);
    }

    void dfs_sub(int x, int p) {
        for(auto &e : g[x]) {
            if(e.to == p) continue;
            dfs_sub(e.to, x);
            e.dp = gg(subdp[e.to], e);
            subdp[x] = f(subdp[x], e.dp);
        }
    }

    stack<tuple<int, int, sum_t>> st;

    void dfs_all(int x, int p, sum_t top) {
        sum_t now = id;
        for(int i = 0; i < (int)g[x].size(); i++) {
            auto &e = g[x][i];
            e.ndp = now;
            if(e.to == p) e.dp = gg(top, e);
            now = f(now, e.dp);
        }
        dp[x] = now;
        now = id;
        for(int i = (int)g[x].size() - 1; i >= 0; i--) {
            auto &e = g[x][i];
            if(e.to != p) st.emplace(e.to, x, f(e.ndp, now));
            now = f(now, e.dp);
        }
    }

    vector<sum_t> build() {
        dfs_sub(0, -1);
        st.emplace(0, -1, id);
        while(!empty(st)) {
            auto [a, b, c] = st.top();
            st.pop();
            dfs_all(a, b, c);
        }
        return dp;
    }
};

int main() {
    while(1) {
        INT(n);
        if(!n) exit(0);
        STR(s);
        vi a;
        for(auto e : s) a.eb(e - '0');
        Graph g(n);
        rep2(i, 1, n - 1) {
            INT(x);
            add(g, i, x - 1);
        }
        constexpr int M = 3;
        struct A {
            pii rev[M];
            pii go[M];
            A() { rep(i, M) rev[i].fi = -inf<int>, go[i].fi = -inf<int>; }
        };

        auto f = [](A p, A q) {
            pii rev[M * 2], go[M * 2];
            rep(i, M) rev[i] = p.rev[i], rev[i + M] = q.rev[i];
            rep(i, M) go[i] = p.go[i], go[i + M] = q.go[i];
            sort(rev, rev + M * 2, greater{}), sort(go, go + M * 2, greater{});
            A res;
            rep(i, M) res.rev[i] = rev[i], res.go[i] = go[i];
            return res;
        };

        auto gg = [&](A p, ReRooting<int, A>::Edge e) {
            if(a[e.to] == 2) {
                A res;
                res.rev[1] = pii(1, e.to + n);
                res.go[1] = pii(1, e.to + n);
                rep(i, M) rep(j, M) {
                    if(p.rev[i].se % n != p.go[j].se % n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    } else if(p.rev[i].se >= n and p.go[j].se >= n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    }
                }
                rep(i, M) rep(j, i) if(p.rev[i].se % n != p.rev[j].se % n) chmax(res.go[0], pii(p.rev[i].fi + p.rev[j].fi + 2, e.to));
                chmax(res.go[1], pii(1 + p.go[0].fi, e.to + n));
                chmax(res.go[1], pii(1 + p.rev[0].fi, e.to + n));
                chmax(res.go[0], pii(2 + p.rev[0].fi, e.to));
                chmax(res.rev[0], pii(2 + p.rev[0].fi, e.to));
                return res;
            } else {
                A res;
                res.rev[0] = pii(1, e.to);
                res.go[0] = pii(max(1, p.go[0].fi + 1), e.to);
                return res;
            }
        };

        ReRooting<int, A> rr(g, gg, f, A());

        auto res = rr.build();

        int ma = 1;

        rep(i, n) {
            if(a[i] == 2) {
                rep(x, M) rep(y, M) {
                    if(res[i].rev[x].se % n != res[i].go[y].se % n)
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    else if(res[i].rev[x].se >= n and res[i].go[y].se >= n) {
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    }
                }
                rep(j, M) {
                    chmax(ma, res[i].go[j].fi + 1);
                    chmax(ma, res[i].rev[j].fi + 2);
                }
            } else {
                rep(j, M) chmax(ma, res[i].go[j].fi + 1);
                rep(j, M) chmax(ma, res[i].rev[j].fi + 1);
            }
        }

        if(ma == 12) {
            OUT(s);
            rep(i, n) { OUT(g[i]); }
        }
        OUT(ma);
    }
}
accuracy: 1
time_ms: 610
memory_kb: 82588
final_rank: 13

code_snippet: //#define _GLIBCXX_DEBUG

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

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
template<typename T>
struct Diameter{
  int n;
  Graph<T> &g;
  vector<bool>used;
  Diameter(Graph<T>&G):g(G),n(G.size()),used(G.size()){
    build(0);
    fill(used.begin(),used.end(),false);
  }
  int root,end;
  long long diam = 0;
  void build(int start){
    long long dmx = -1;
    dfs(start,0,-1,root,dmx);
    diam = -1;
    dfs(root,0,-1,end,diam);
  }
  void dfs(int k, long long d,int par, int &vmx, long long &dmx){
    used[k]=true;
    if(dmx < d){
      dmx = d;
      vmx = k;
    }
    for(auto e:g[k]){
      if(par != e.to)dfs(e.to,d+e.cost,k,vmx,dmx);
    }
  }
};
template<typename T>
vector<ll> bfs(Graph<T> &g,int s=0){
  vector<ll>dist(g.size(),INF);
  queue<int>que;
  ll n=g.size();
  que.push(s);
  dist[s]=0;
  while(!que.empty()){
    int x=que.front();
    que.pop();
    for(auto to:g[x]){
      if(dist[to]==INF){
        dist[to]=dist[x]+1;
        que.push(to);
      }
    }
  }
  return dist;
}
template< typename sum_t, typename key_t >
struct ReRooting {
  struct Edge {
    int to;
    key_t data;
    sum_t dp, ndp;
  };

  using F = function< sum_t(sum_t, sum_t) >;
  using G = function< sum_t(sum_t, key_t) >;

  vector< vector< Edge > > g;
  vector< sum_t > subdp, dp;
  vector< sum_t > init;
  const sum_t ident;
  const F f;
  const G gg;

  ReRooting(int V, const F f, const G g, const sum_t &ident)
      : g(V), f(f), gg(g), ident(ident), subdp(V, ident), dp(V, ident), init(V, ident) {}

  void add_edge(int u, int v, const key_t &d) {
    g[u].emplace_back((Edge) {v, d, ident, ident});
    g[v].emplace_back((Edge) {u, d, ident, ident});
  }

  void add_edge_bi(int u, int v, const key_t &d, const key_t &e) {
    g[u].emplace_back((Edge) {v, d, ident, ident});
    g[v].emplace_back((Edge) {u, e, ident, ident});
  }

  void set(int idx, sum_t s){
    subdp[idx] = s;
    init[idx] = s;
  }
  void dfs_sub(int idx, int par) {
    for(auto &e : g[idx]) {
      if(e.to == par) continue;
      dfs_sub(e.to, idx);
      subdp[idx] = f(subdp[idx], gg(subdp[e.to], e.data));
    }
  }

  void dfs_all(int idx, int par, const sum_t &top) {
    sum_t buff{init[idx]};
    for(int i = 0; i < (int) g[idx].size(); i++) {
      auto &e = g[idx][i];
      e.ndp = buff;
      e.dp = gg(par == e.to ? top : subdp[e.to], e.data);
      buff = f(buff, e.dp);
    }
    dp[idx] = buff;
    buff = ident;
    for(int i = (int) g[idx].size() - 1; i >= 0; i--) {
      auto &e = g[idx][i];
      if(e.to != par) dfs_all(e.to, idx, f(e.ndp, buff));
      e.ndp = f(e.ndp, buff);
      buff = f(buff, e.dp);
    }
  }

  vector< sum_t > build() {
    dfs_sub(0, -1);
    dfs_all(0, -1, ident);
    return dp;
  }
};
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  while(1){
    ll n;cin>>n;
    if(n==0)break;
    //cout<<n<<endl;
    vector<ll>x(n);
    string s;cin>>s;
    rep(i,0,n)x[i]=s[i]-'0';
    struct A{
      //片道最大
      ll mi1;
      //戻ってきている最大
      ll mi2;
      //戻ってきている+片道の最大
      ll mi3;
      //戻ってこれればの最大
      ll mi4;
      bool v;
    };
    auto f1=[&](A x,A y)->A{
      A z;
      z.mi1=max(x.mi1,y.mi1);
      z.mi2=max(x.mi2,y.mi2);
      z.mi3=max({x.mi3,y.mi3,x.mi1+y.mi2,x.mi2+y.mi1});
      z.mi4=max({x.mi4,y.mi4});
      z.v=x.v&&y.v;
      //cout<<x.v spa y.v spa z.v<<endl;
      return z;
    };
    auto f2=[&](A x,ll w)->A{
      //cout<<w spa x.v<<endl;
      if(!x.v){
        return{
          max({1LL,x.mi1+1,x.mi2+1}),
          1LL,
          -INF,
          1LL,
          true
        };
      }
      else{
        return{
          max({x.mi1+1,x.mi2+2,x.mi3+2,x.mi4+2}),
          max({1LL,x.mi2+2}),
          -INF,
          max({2LL,2+x.mi1}),
          true
        };
      }
    };
    auto print=[&](A x){
      cout<<x.mi1 spa x.mi2 spa x.mi3 spa x.v<<endl;
    };
    ReRooting<A,ll>rer(n,f1,f2,A{-INF,-INF,-INF,-INF,true});
    rep(i,0,n){
      if(x[i]==1)rer.set(i,{-INF,-INF,-INF,-INF,false});
      else rer.set(i,{-INF,-INF,-INF,-INF,true});
    }
    rep(i,1,n){
      ll p;cin>>p;p--;
      rer.add_edge(p,i,1);
    }
    auto v=rer.build();
    ll ret=0;
    rep(i,0,n){
      auto tmp=f2(v[i],1);
      chmax(ret,tmp.mi1);
      chmax(ret,tmp.mi2);
      chmax(ret,tmp.mi3);
      //cout<<tmp.mi1 spa tmp.mi2 spa tmp.mi3 spa tmp.mi4 spa tmp.v<<endl;
    }
    //debug(x);
    /*for(auto e:rer.g[2]){
      cout<<2 spa e.to<<":";print(e.dp);
    }
    for(auto e:rer.g[3]){
      cout<<3 spa e.to<<":";print(e.dp);
    }*/
    cout<<ret<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 98188
final_rank: 11

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

template <typename key_t, typename sum_t = key_t> struct ReRooting {
    struct Edge {
        int from, to;
        key_t cost;
        sum_t dp, ndp;
    };
    using F = function<sum_t(sum_t, sum_t)>;
    using G = function<sum_t(sum_t, Edge)>;

    vector<vector<Edge>> g;
    const F f;
    const G gg;
    const sum_t id;
    vector<sum_t> subdp, dp;

    void add_edge(int u, int v, const key_t &d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, d, id, id});
    }
    void add_edge(int u, int v, const key_t &d, const key_t &rev_d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, rev_d, id, id});
    }
    void add_directed_edge(int u, int v, const key_t &d) { g[u].emplace_back(Edge{u, v, d, id, id}); }

    ReRooting(int n, const G &g, const F &f, const sum_t &id = sum_t{}) : g(n), f(f), gg(g), id(id), subdp(n, id), dp(n, id) {}
    ReRooting(Graph &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, 1);
    }
    template <typename T>
    ReRooting(Wgraph<T> &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, e.cost);
    }

    void dfs_sub(int x, int p) {
        for(auto &e : g[x]) {
            if(e.to == p) continue;
            dfs_sub(e.to, x);
            e.dp = gg(subdp[e.to], e);
            subdp[x] = f(subdp[x], e.dp);
        }
    }

    void dfs_all(int x, int p, sum_t top) {
        sum_t now = id;
        for(int i = 0; i < (int)g[x].size(); i++) {
            auto &e = g[x][i];
            e.ndp = now;
            if(e.to == p) e.dp = gg(top, e);
            now = f(now, e.dp);
        }
        dp[x] = now;
        now = id;
        for(int i = (int)g[x].size() - 1; i >= 0; i--) {
            auto &e = g[x][i];
            if(e.to != p) dfs_all(e.to, x, f(e.ndp, now));
            now = f(now, e.dp);
        }
    }

    vector<sum_t> build() {
        dfs_sub(0, -1);
        dfs_all(0, -1, id);
        return dp;
    }
};

int main() {
    while(1) {
        INT(n);
        if(!n) exit(0);
        STR(s);
        vi a;
        for(auto e : s) a.eb(e - '0');
        Graph g(n);
        rep2(i, 1, n - 1) {
            INT(x);
            add(g, i, x - 1);
        }
        constexpr int M = 2;
        struct A {
            pii rev[M];
            pii go[M];
            A() { rep(i, M) rev[i].fi = -inf<int>, go[i].fi = -inf<int>; }
        };

        auto f = [](A p, A q) {
            pii rev[M * 2], go[M * 2];
            rep(i, M) rev[i] = p.rev[i], rev[i + M] = q.rev[i];
            rep(i, M) go[i] = p.go[i], go[i + M] = q.go[i];
            sort(rev, rev + M * 2, greater{}), sort(go, go + M * 2, greater{});
            A res;
            rep(i, M) res.rev[i] = rev[i], res.go[i] = go[i];
            return res;
        };

        auto gg = [&](A p, ReRooting<int, A>::Edge e) {
            if(a[e.to] == 2) {
                A res;
                res.rev[1] = pii(1, e.to + n);
                res.go[1] = pii(1, e.to + n);
                rep(i, M) rep(j, M) {
                    if(p.rev[i].se % n != p.go[j].se % n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    } else if(p.rev[i].se >= n and p.go[j].se >= n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    }
                }
                rep(i, M) rep(j, i) if(p.rev[i].se % n != p.rev[j].se % n) chmax(res.go[0], pii(p.rev[i].fi + p.rev[j].fi + 2, e.to));
                chmax(res.go[1], pii(1 + p.go[0].fi, e.to + n));
                chmax(res.go[1], pii(1 + p.rev[0].fi, e.to + n));
                chmax(res.go[0], pii(2 + p.rev[0].fi, e.to));
                chmax(res.rev[0], pii(2 + p.rev[0].fi, e.to));
                return res;
            } else {
                A res;
                res.rev[0] = pii(1, e.to);
                res.go[0] = pii(max(1, p.go[0].fi + 1), e.to);
                return res;
            }
        };

        ReRooting<int, A> rr(g, gg, f, A());

        auto res = rr.build();

        int ma = 1;

        rep(i, n) {
            if(a[i] == 2) {
                rep(x, M) rep(y, M) {
                    if(res[i].rev[x].se % n != res[i].go[y].se % n)
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    else if(res[i].rev[x].se >= n and res[i].go[y].se >= n) {
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    }
                }
                rep(j, M) {
                    chmax(ma, res[i].go[j].fi + 1);
                    chmax(ma, res[i].rev[j].fi + 2);
                }
            } else {
                rep(j, M) chmax(ma, res[i].go[j].fi + 1);
                rep(j, M) chmax(ma, res[i].rev[j].fi + 1);
            }
        }

        if(ma == 12) {
            OUT(s);
            rep(i, n) { OUT(g[i]); }
        }
        OUT(ma);
    }
}
accuracy: 0.5
time_ms: 520
memory_kb: 84784
final_rank: 14

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

template <typename key_t, typename sum_t = key_t> struct ReRooting {
    struct Edge {
        int from, to;
        key_t cost;
        sum_t dp, ndp;
    };
    using F = function<sum_t(sum_t, sum_t)>;
    using G = function<sum_t(sum_t, Edge)>;

    vector<vector<Edge>> g;
    const F f;
    const G gg;
    const sum_t id;
    vector<sum_t> subdp, dp;

    void add_edge(int u, int v, const key_t &d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, d, id, id});
    }
    void add_edge(int u, int v, const key_t &d, const key_t &rev_d) {
        g[u].emplace_back(Edge{u, v, d, id, id});
        g[v].emplace_back(Edge{v, u, rev_d, id, id});
    }
    void add_directed_edge(int u, int v, const key_t &d) { g[u].emplace_back(Edge{u, v, d, id, id}); }

    ReRooting(int n, const G &g, const F &f, const sum_t &id = sum_t{}) : g(n), f(f), gg(g), id(id), subdp(n, id), dp(n, id) {}
    ReRooting(Graph &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, 1);
    }
    template <typename T>
    ReRooting(Wgraph<T> &graph, const G &g, const F &f, const sum_t &id = sum_t{})
        : g(graph.size()), f(f), gg(g), id(id), subdp(graph.size(), id), dp(graph.size(), id) {
        for(int i = 0; i < graph.size(); i++)
            for(auto e : graph[i]) add_directed_edge(i, e, e.cost);
    }

    void dfs_sub(int x, int p) {
        for(auto &e : g[x]) {
            if(e.to == p) continue;
            dfs_sub(e.to, x);
            e.dp = gg(subdp[e.to], e);
            subdp[x] = f(subdp[x], e.dp);
        }
    }

    void dfs_all(int x, int p, sum_t top) {
        sum_t now = id;
        for(int i = 0; i < (int)g[x].size(); i++) {
            auto &e = g[x][i];
            e.ndp = now;
            if(e.to == p) e.dp = gg(top, e);
            now = f(now, e.dp);
        }
        dp[x] = now;
        now = id;
        for(int i = (int)g[x].size() - 1; i >= 0; i--) {
            auto &e = g[x][i];
            if(e.to != p) dfs_all(e.to, x, f(e.ndp, now));
            now = f(now, e.dp);
        }
    }

    vector<sum_t> build() {
        dfs_sub(0, -1);
        dfs_all(0, -1, id);
        return dp;
    }
};

int main() {
    while(1) {
        INT(n);
        if(!n) exit(0);
        STR(s);
        vi a;
        for(auto e : s) a.eb(e - '0');
        Graph g(n);
        rep2(i, 1, n - 1) {
            INT(x);
            add(g, i, x - 1);
        }
        struct A {
            pii rev[2];
            pii go[2];
            A() { rep(i, 2) rev[i].fi = -inf<int>, go[i].fi = -inf<int>; }
        };

        auto f = [](A p, A q) {
            pii rev[4], go[4];
            rep(i, 2) rev[i] = p.rev[i], rev[i + 2] = q.rev[i];
            rep(i, 2) go[i] = p.go[i], go[i + 2] = q.go[i];
            sort(rev, rev + 4, greater{}), sort(go, go + 4, greater{});
            A res;
            rep(i, 2) res.rev[i] = rev[i], res.go[i] = go[i];
            return res;
        };

        auto gg = [&](A p, ReRooting<int, A>::Edge e) {
            if(a[e.to] == 2) {
                A res;
                res.rev[1] = pii(1, e.to + n);
                res.go[1] = pii(1, e.to + n);
                rep(i, 2) rep(j, 2) {
                    if(p.rev[i].se % n != p.go[j].se % n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    } else if(p.rev[i].se >= n and p.go[j].se >= n) {
                        chmax(res.go[0], pii(p.rev[i].fi + p.go[j].fi + 2, e.to));
                    }
                }
                if(p.rev[0].se % n != p.rev[1].se % n) chmax(res.go[0], pii(p.rev[0].fi + p.rev[1].fi + 2, e.to));
                chmax(res.go[1], pii(1 + p.go[0].fi, e.to + n));
                chmax(res.go[1], pii(1 + p.rev[0].fi, e.to + n));
                chmax(res.go[0], pii(2 + p.rev[0].fi, e.to));
                chmax(res.rev[0], pii(2 + p.rev[0].fi, e.to));
                return res;
            } else {
                A res;
                res.rev[0] = pii(1, e.to);
                res.go[0] = pii(max(1, p.go[0].fi + 1), e.to);
                return res;
            }
        };

        ReRooting<int, A> rr(g, gg, f, A());

        auto res = rr.build();

        int ma = 1;

        rep(i, n) {
            if(a[i] == 2) {
                rep(x, 2) rep(y, 2) {
                    if(res[i].rev[x].se % n != res[i].go[y].se % n)
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    else if(res[i].rev[x].se >= n and res[i].go[y].se >= n) {
                        chmax(ma, res[i].rev[x].fi + res[i].go[y].fi + 2);
                    }
                }
                chmax(ma, res[i].go[0].fi + 1);
                chmax(ma, res[i].rev[0].fi + 2);
            } else {
                chmax(ma, res[i].go[0].fi + 1);
            }
        }
        OUT(ma);
    }
}
accuracy: 0.5
time_ms: 530
memory_kb: 84768
final_rank: 15

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

#define rep(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define ALL(v) (v).begin(),(v).end()
using ll=long long int;
const int inf = 0x3fffffff; const ll INF = 0x1fffffffffffffff; const double eps=1e-12;
template<typename T>inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<typename T>inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}

template<typename M,typename N,M (*f)(M,N),M (*g)(M,int),M (*h)(M,M),M (*e)()>struct Rerooting{
    using P=pair<int,N>;
    vector<vector<P>> G;
    vector<M> buf,ret;
    Rerooting(int n):G(n),buf(n,e()),ret(n){}
    void add_edge(int u,int v,N w){
        G[u].push_back({v,w});
        G[v].push_back({u,w});
    }
    void dfs1(int v,int p){
        for(auto& [to,w]:G[v])if(to!=p){
            dfs1(to,v);
            buf[v]=h(buf[v],f(buf[to],w));
       }
       buf[v]=g(buf[v],v);
    }
    void dfs2(int v,int p,M pc){
        buf[v]=e();
        vector<M> cs;
        for(auto& [to,w]:G[v])if(to!=p){
            cs.push_back(f(buf[to],w));
            buf[v]=h(buf[v],f(buf[to],w));
        }
        buf[v]=g(h(buf[v],pc),v);
        ret[v]=buf[v];
        cs.push_back(pc);
        int m=cs.size();
        vector<M> L(m),R(m);
        rep(i,0,m){
            L[i]=cs[i];
            if(i)L[i]=h(L[i],L[i-1]);
        }
        for(int i=m-1;i>=0;i--){
            R[i]=cs[i];
            if(i!=m-1)R[i]=h(R[i],R[i+1]);
        }
        int id=0;
        for(auto& [to,w]:G[v])if(to!=p){
            M nxt=e();
            if(id!=0)nxt=h(nxt,L[id-1]);
            if(id!=m-1)nxt=h(nxt,R[id+1]);
            M buf_v=buf[v],buf_to=buf[to];
            buf[v]=g(nxt,v);
            M add=f(buf[v],w);
            dfs2(to,v,add);
            buf[v]=buf_v,buf[to]=buf_to;
            id++;
        }
    }
    vector<M> run(){
        dfs1(0,-1);
        dfs2(0,-1,e());
        return ret;
    }
};

string s;
struct X{
    int dp1=-inf;
    int dp2=-inf;
    int dp3=-inf;
    int buf=-inf;
};
X f(X a,int c){
    return a;
}
X g(X a,int v){
    X ret;
    if(s[v]=='1'){
        ret.dp1=max({1,a.dp1+1,a.dp2+1});
        ret.dp2=1;
        ret.dp3=-inf;
        ret.buf=1;
    }
    else{
        ret.dp1=max({a.dp1+1,a.dp2+2,a.dp3+2,a.buf+2});
        ret.dp2=max(1,a.dp2+2);
        ret.dp3=-inf;
        ret.buf=max(2,a.dp1+2);
    }
    return ret;
}
X h(X a,X b){
    X ret;
    ret.dp1=max({a.dp1,b.dp1});
    ret.dp2=max(a.dp2,b.dp2);
    ret.dp3=max({a.dp3,b.dp3,a.dp2+b.dp1,b.dp2+a.dp1});
    ret.buf=max(a.buf,b.buf);
    return ret;
}
X e(){
    return X();
}

void solve(){
    int n;
    cin>>n;
    if(n==0)exit(0);
    cin>>s;
    Rerooting<X,int,f,g,h,e> tree(n);
    rep(x,1,n){
        int p;
        cin>>p;
        tree.add_edge(x,p-1,1);
    }

    auto ret=tree.run();
    int res=0;
    rep(i,0,n)chmax(res,max({ret[i].dp1,ret[i].dp2,ret[i].dp3}));
    cout<<res<<'\n';
}

int main(){
    for(;;)solve();
    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 44276
final_rank: 7

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}


const int mn = 1 << 17;
struct edge {
	int to;
};
using Data = array<int, 3>;
vector<edge> G[mn];
vector<int> ids[mn];
vector<Data> memo[mn];
int a[mn];
int root;

void init(int n) {
	rep(i, n) {
		G[i].clear();
		ids[i].clear();
		memo[i].clear();
	}
}

int ci = 0, cj = 0;
int calc(vector<Data>& np) {
	ci = -1, cj = -1;
	if (np.size() <= 1)return -mod;
	multiset<P> st;
	rep(i, np.size()) {
		st.insert({ np[i][2],i });
	}
	int res = -mod;
	rep(i, np.size()) {
		Data d = np[i];
		P p = { d[2],i };
		st.erase(st.find(p));
		int val = max(d[0], d[1]) + (*--st.end()).first;
		if (res < val) {
			res = val;
			ci = i;
			cj = (*--st.end()).second;
		}
		st.insert(p);
	}
	return res;
}
Data dfs(int id, int fr) {
	Data res;
	//
	//initialize
	//
	vector<Data> np;
	for (edge e : G[id]) {
		if (e.to == fr)continue;
		Data nex = dfs(e.to, id);
		//
		//update with edge
		//
		np.push_back(nex);
		ids[id].push_back(e.to);
		memo[id].push_back(nex);
	}
	//
	//update for return
	res = { 1,-mod,1 };
	rep(i, 3) {
		if (i == 0) {
			for (Data d : np) {
				res[0] = max(res[0], max(d[0], d[1]) + 1);
			}
		}
		else if (i == 1) {
			if (a[id] == 2) {
				//down up down
				rep(j, np.size()) {
					Data d = np[j];
					int to = ids[id][j];
					if (a[to] == 2) {
						res[1] = max(res[1], 3 + d[0]);
					}
				}
				//down up another down
				res[1] = max(res[1], calc(memo[id]) + 2);
				/*multiset<int> st;
				rep(j, np.size()) {
					Data d = np[j];
					st.insert(d[2]);
				}
				rep(j, np.size()) {
					Data d = np[j];
					st.erase(st.find(d[2]));
					if (st.size()) {
						int val = max(d[0], d[1]) + 2 + *--st.end();
						res[1] = max(res[1], val);
					}
					st.insert(d[2]);
				}*/
			}

		}
		else {
			if (a[id] == 2) {
				for (Data d : np) {
					res[2] = max(res[2], d[2] + 2);
				}
			}
		}
	}
	res[1] = max(res[1], res[2]);
	if (id == 4) {
		//cout << res[0] << " "<<res[1]<<" "<<res[2]<<"\n";
	}
	return res;
}
int ans = 0;
void invdfs(int id, int fr, Data pre) {
	vector<Data> v;
	for (Data d : memo[id])v.push_back(d);
	if (fr >= 0)v.push_back(pre);
	int len = v.size();
	//
	//calcurate id's ans
	Data res = { 1,-mod,1 };
	vector<Data>& np = v;
	rep(i, 3) {
		if (i == 0) {
			for (Data d : np) {
				res[0] = max(res[0], max(d[0], d[1]) + 1);
			}
		}
		else if (i == 1) {
			if (a[id] == 2) {
				//down up down
				rep(j, np.size()) {
					Data d = np[j];
					int to;
					if (j < ids[id].size())to = ids[id][j];
					else to = fr;
					if (a[to] == 2) {
						res[1] = max(res[1], 3 + d[0]);
					}
				}
				//down up another down
				res[1] = max(res[1], calc(np) + 2);
				/*multiset<int> st;
				rep(j, np.size()) {
					Data d = np[j];
					st.insert(d[2]);
				}
				rep(j, np.size()) {
					Data d = np[j];
					st.erase(st.find(d[2]));
					if (st.size()) {
						int val = max(d[0], d[1]) + 2 + *--st.end();
						res[1] = max(res[1], val);
					}
					st.insert(d[2]);
				}*/
			}

		}
		else {
			if (a[id] == 2) {
				for (Data d : np) {
					res[2] = max(res[2], d[2] + 2);
				}
			}
		}
	}
	if (max({ res[0],res[1],res[2] }) == 13) {
		//cout << "? " << id << "\n";
	}
	rep(i, 3)ans = max(ans, res[i]);

	vector<Data> nd(ids[id].size());
	rep(i, ids[id].size()) {
		nd[i] = { 1,-mod,1 };
	}
	//0
	multiset<int> st;
	for (Data d : np) {
		st.insert(max(d[0], d[1]));
	}
	rep(i, ids[id].size()) {
		Data d = np[i];
		int val = max(d[0], d[1]);
		st.erase(st.find(val));
		if (st.size()) {
			nd[i][0] = max(nd[i][0], *--st.end() + 1);
		}
		st.insert(val);
	}
	//1
	if (a[id] == 2) {
		multiset<int> st;
		rep(i, np.size()) {
			Data d = np[i];
			int to;
			if (i < ids[id].size())to = ids[id][i];
			else to = fr;
			if (a[to] == 2)st.insert(d[0]);
		}
		rep(i, ids[id].size()) {
			int to = ids[id][i];
			Data d = np[i];
			if (a[to] == 2) {
				st.erase(st.find(d[0]));
			}
			if (st.size()) {
				int val = *--st.end();
				nd[i][1] = max(nd[i][1], val + 3);
			}
			if (a[to] == 2) {
				st.insert(d[0]);
			}
		}
		int val = calc(np);
		int memoi = ci;
		int memoj = cj;
		rep(i, ids[id].size()) {
			if (i == memoi || i == memoj) {
				vector<Data> vv = np;
				vv.erase(vv.begin() + i);
				int nval = calc(vv);
				nd[i][1] = max(nd[i][1], nval + 2);
			}
			else {
				nd[i][1] = max(nd[i][1], val + 2);
			}
		}
	}
	//2
	if (a[id] == 2) {
		multiset<int> st;
		for (Data d : np) {
			st.insert(d[2]);
		}
		rep(i, ids[id].size()) {
			Data d = np[i];
			st.erase(st.find(d[2]));
			if (st.size()) {
				nd[i][2] = max(nd[i][2], *--st.end() + 2);
			}
			st.insert(d[2]);
		}
	}
	rep(i, ids[id].size()) {
		int to = ids[id][i];
		Data d = nd[i];
		d[1] = max(d[1], d[2]);
		//
		//update for return
		//

		if (id == 1 && to == 2) {
			//cout << d[0] << " "<<d[1]<<" "<<d[2]<<"\n";
		}
		invdfs(to, id, d);
	}
}
void yaru() {
	dfs(root, -1);
	invdfs(root, -1, { -mod,-mod,-mod });
}
int n;
void solve() {
	init(n);
	string s; cin >> s;
	rep(i, n)a[i] = s[i] - '0';
	rep1(i, n - 1) {
		int p; cin >> p; p--;
		G[p].push_back({ i });
		G[i].push_back({ p });
	}
	ans = 0;
	yaru();
	//cout << "ans is ";
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(8);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	while (cin >> n, n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 68232
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>

#include <algorithm>
#include <cassert>
#include <vector>


#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    segtree(int n) : segtree(std::vector<S>(n, e())) {}
    segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

using namespace std;
int N;
string X;
vector<int>G[1<<17];
int dp[1<<17][3];
void dfs1(int u)
{
	dp[u][0]=1;
	dp[u][1]=1;
	dp[u][2]=1;
	int mx2=-1;
	for(int v:G[u])
	{
		dfs1(v);
		dp[u][0]=max(dp[u][0],dp[v][0]+1);
		dp[u][2]=max(dp[u][2],dp[v][0]+1);
		if(X[u]=='2')
		{
			dp[u][1]=max(dp[u][1],dp[v][1]+2);
			if(X[v]=='2')
			{
				dp[u][0]=max(dp[u][0],dp[v][2]+3);
			}
		}
		if(mx2==-1||dp[mx2][1]<dp[v][1])mx2=v;
	}
	if(X[u]=='2'&&mx2!=-1)
	{
		int n0=0,n1=-1e9;
		for(int v:G[u])if(v!=mx2)
		{
			n0=max(n0,dp[v][0]);
			n1=max(n1,dp[v][1]);
		}
		dp[u][0]=max(dp[u][0],max(dp[mx2][1]+2+n0,dp[mx2][0]+2+n1));
	}
	//cout<<"dp["<<u<<"] = ("<<dp[u][0]<<", "<<dp[u][1]<<", "<<dp[u][2]<<")"<<endl;
}
using dat=pair<int,int>;
dat op(dat a,dat b){return a<b?b:a;}
dat e(){return make_pair(-1e9,-1);}
int ans;
void dfs2(int u,int p0,int p1,int p2,char pc)
{
	//cout<<u<<" <- ("<<p0<<", "<<p1<<", "<<p2<<")"<<endl;
	{
		int now0=max(dp[u][0],p0+1);
		ans=max(ans,now0);
		if(X[u]=='2')
		{
			int n0=0,n1=-1e9;
			for(int v:G[u])
			{
				n0=max(n0,dp[v][0]);
				n1=max(n1,dp[v][1]);
			}
			ans=max(ans,max(p1+2+n0,p0+2+n1));
			if(pc=='2')
			{
				ans=max(ans,p2+3);
			}
		}
	}
	int n=G[u].size();
	vector<dat>in0(n+1),in1(n+1),in2(n+1,e());
	in0[n]=make_pair(p0,n);
	in1[n]=make_pair(p1,n);
	if(pc=='2')in2[n]=make_pair(p2,n);
	for(int i=0;i<n;i++)
	{
		in0[i]=make_pair(dp[G[u][i]][0],i);
		in1[i]=make_pair(dp[G[u][i]][1],i);
		if(X[G[u][i]]=='2')in2[i]=make_pair(dp[G[u][i]][2],i);
	}
	atcoder::segtree<dat,op,e>P0(in0),P1(in1),P2(in2);
	for(int i=0;i<n;i++)
	{
		int np1=1;
		if(X[u]=='2')
		{
			np1=max(np1,max(P1.prod(0,i).first,P1.prod(i+1,n+1).first)+2);
		}
		int np2=max(1,max(P0.prod(0,i).first,P0.prod(i+1,n+1).first)+1);
		int np0=np2;
		if(X[u]=='2')
		{
			np0=max(np0,max(P2.prod(0,i).first,P2.prod(i+1,n+1).first)+3);
		}
		if(X[u]=='2')
		{
			dat tmp=op(P1.prod(0,i),P1.prod(i+1,n+1));
			if(tmp.second>=0)
			{
				int l=tmp.second,r=i;
				if(l>r)swap(l,r);
				np0=max(np0,tmp.first+2+max({P0.prod(0,l).first,P0.prod(l+1,r).first,P0.prod(r+1,n+1).first}));
				np0=max(np0,P0.get(tmp.second).first+2+max({P1.prod(0,l).first,P1.prod(l+1,r).first,P1.prod(r+1,n+1).first}));
			}
		}
		dfs2(G[u][i],np0,np1,np2,X[u]);
	}
}
int main()
{
	while(cin>>N,N)
	{
		cin>>X;
		for(int i=0;i<N;i++)G[i].clear();
		for(int i=1;i<N;i++)
		{
			int p;cin>>p;
			G[p-1].push_back(i);
		}
		dfs1(0);
		ans=0;
		dfs2(0,0,-1e9,0,'1');
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 340
memory_kb: 56128
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cstdio>
using namespace std;

#define ALL(v) begin(v),end(v)

using pii = pair<int,int>;

const int INF = 101010101;

void chmax(int &a, int b){
	if(a < b){ a = b; }
}

struct solver{
	string xs;
	vector<vector<int>> children;
	vector<int> par;
	vector<int> rttd, rtta, cowm;
	vector<vector<pii>> crttop;
	int ans;
	int solve(int n){
		cin >> xs;
		children.resize(n);
		par.resize(n);
		par[0] = -1;
		for(int i = 1; i < n; ++i){
			int p;
			cin >> p;
			--p;
			children[p].push_back(i);
			par[i] = p;
		}

		rttd.resize(n);
		rtta.resize(n);
		crttop.resize(n);
		cowm.resize(n);
		dfs1(0);
		dfs2(0);
		dfs3(0);

#ifdef DBG
for(int i=0;i<n;++i){
fprintf(stderr,"node %d: %d %d;",i,rttd[i],rtta[i]);
for(auto p:crttop[i]){
if(p.first>=0)
fprintf(stderr," (%d, %d)", p.first,p.second);
}fprintf(stderr,"\n");
}
#endif
		return ans;
	}

	int dfs1(int u){
		int &r = rttd[u];
		r = 1;
		crttop[u].assign(3, pii(-INF, -INF));
		for(int v : children[u]){
			int x = dfs1(v);
			if(xs[u] == '2'){
				chmax(r, x + 2);
			}
			pii p(x, v);
			crttop[u].insert(lower_bound(ALL(crttop[u]), p, greater<pii>()), p);
			crttop[u].pop_back();
		}
		chmax(ans, r);
		return r;
	}
	
	void dfs2(int u){
		int &r = rtta[u];
		r = 1;
		int p = par[u];
		if(xs[u] == '2' && p != -1){
			chmax(r, rtta[p] + 2);
			if(xs[p] == '2'){
				for(const pii &q : crttop[p]){
					if(q.second != u){
						chmax(r, q.first + 4);
					}
				}
			}
		}
		chmax(ans, r);
		
		for(int v : children[u]){
			dfs2(v);
		}
	}
	
	int dfs3(int u){
		vector<pii> cowtop(3, pii(0, -INF));
		for(int v : children[u]){
			int x = dfs3(v);
			pii p(x, v);
			cowtop.insert(lower_bound(ALL(cowtop), p, greater<pii>()), p);
			cowtop.pop_back();
		}
#ifdef DBG
fprintf(stderr,"cowtop %d:",u);
for(const auto &p: cowtop){
if(p.second!=-INF){fprintf(stderr," (%d, %d)",p.first,p.second);}
}
fprintf(stderr,"\n");
#endif
		int &r = cowm[u];
		r = cowtop[0].first + 1;
		chmax(ans, r + cowtop[1].first);
		if(xs[u] == '2'){
			for(int i = 0; i < 3; ++i)
			for(int j = 0; j < i; ++j){
				pii p1 = cowtop[i], p2 = cowtop[j];
				int b = rtta[u];
				for(const pii &q : crttop[u]){
					if(q.second != p1.second && q.second != p2.second){
						chmax(b, q.first + 2);
					}
				}
#ifdef DBG
fprintf(stderr,"%d: %d+%d+%d; %d, %d\n",u,p1.first,p2.first,b,p1.second,p2.second);
#endif
				chmax(ans, p1.first + p2.first + b);
			}
			
			for(const pii &p1 : cowtop)
			for(const pii &p2 : crttop[u]){
				if(p1.second != p2.second){
					chmax(r, p1.first + p2.first + 2);
				}
			}
			
			for(int v : children[u]){
				if(xs[v] == '2'){
					int m = 0;
					for(int w : children[v]){
						chmax(m, cowm[w]);
					}
					chmax(r, m + 4);
					for(const pii &p : cowtop){
						if(p.second != v){
#ifdef DBG
fprintf(stderr,"tt %d: %d+4+%d (%d,%d)\n",m,4,p.first,v,p.second);
#endif
							chmax(ans, m + 4 + p.first);
						}
					}
				}
			}
		}
		chmax(ans, r);
#ifdef DBG
fprintf(stderr,"ret %d: %d\n",u,r);
#endif
		return r;
	}
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	while(cin >> n && n){
		int ans = solver().solve(n);
		cout << ans << "\n";
	}
}
accuracy: 1
time_ms: 240
memory_kb: 35764
final_rank: 6

code_snippet: #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
void chmax(int& a, int b){ if(a < b) a = b; }


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    while(1){
        int N;
        cin >> N;
        if(N == 0) return 0;
        string x;
        cin >> x;
        for(char& c : x){
            c -= '0';
            c *= 2;
        }
        vector<vector<int>> g(N);
        for(int i = 1; i < N; i++){
            int p;
            cin >> p;
            g[--p].push_back(i);
        }
        // dp[root of subtree][#endpoint][degree pf root] = max #edge
        int dp[N][3][5];
        memset(dp, 0xee, sizeof dp);
        int ans = 0;
        for(int a = N; a--; ){
            auto dp1 = dp[a];
            dp1[0][0] = 0;
            for(int b : g[a]){
                auto dp2 = dp[b];
                int dp3[3][5];
                memcpy(dp3, dp1, sizeof dp3);
                // add k edges between x and y
                for(int k = 1; k <= 3; k++)
                    for(int i1 = 0; i1 <= 2; i1++) for(int i2 = 0; i1 + i2 <= 2; i2++)
                        for(int j1 = 0; j1 <= x[a] - k; j1++) for(int j2 = k % 2; j2 <= x[b] - k; j2 += 2)
                            chmax(dp1[i1 + i2][j1 + k], dp3[i1][j1] + dp2[i2][j2] + k);
            }
            // add endpoint
            for(int i1 = 0; i1 <= 1; i1++) for(int j1 = 0; j1 <= x[a] - 1; j1++)
                chmax(dp1[i1 + 1][j1 + 1], dp1[i1][j1] + 1);
            for(int j1 = 2; j1 <= x[a]; j1 += 2) chmax(ans, dp1[2][j1]);
        }
        cout << ans - 1 << '\n';
    }
}
accuracy: 1
time_ms: 160
memory_kb: 14492
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
void chmax(int& a, int b){ if(a < b) a = b; }


int main(){
    while(1){
        int N;
        cin >> N;
        if(N == 0) return 0;
        string x;
        cin >> x;
        for(char& c : x){
            c -= '0';
            c *= 2;
        }
        vector<vector<int>> g(N);
        for(int i = 1; i < N; i++){
            int p;
            cin >> p;
            g[--p].push_back(i);
        }
        // dp[root of subtree][#endpoint][degree pf root] = max #edge
        int dp[N][3][5];
        memset(dp, 0xee, sizeof dp);
        int ans = 0;
        for(int a = N; a--; ){
            auto dp1 = dp[a];
            dp1[0][0] = 0;
            for(int b : g[a]){
                auto dp2 = dp[b];
                int dp3[3][5];
                memcpy(dp3, dp1, sizeof dp3);
                // add k edges between x and y
                for(int k = 1; k <= 3; k++)
                    for(int i1 = 0; i1 <= 2; i1++) for(int i2 = 0; i1 + i2 <= 2; i2++)
                        for(int j1 = 0; j1 <= x[a] - k; j1++) for(int j2 = k % 2; j2 <= x[b] - k; j2 += 2)
                            chmax(dp1[i1 + i2][j1 + k], dp3[i1][j1] + dp2[i2][j2] + k);
            }
            // add endpoint
            for(int i1 = 0; i1 <= 1; i1++) for(int j1 = 0; j1 <= x[a] - 1; j1++)
                chmax(dp1[i1 + 1][j1 + 1], dp1[i1][j1] + 1);
            for(int j1 = 2; j1 <= x[a]; j1 += 2) chmax(ans, dp1[2][j1]);
        }
        cout << ans - 1 << '\n';
    }
}
accuracy: 1
time_ms: 260
memory_kb: 14460
final_rank: 2