#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

#define mp make_pair
#define pb push_back
#define ll long long

#define maxN 200011
#define lSon (node << 1)
#define rSon (lSon | 1)
#define inf (1001000000)

struct query {
    int node, tm, id;
    int sort_val;

    bool operator<(const query& who)const {
        return mp(sort_val, node) < mp(who.sort_val, who.node);
    }
};

struct segm_tree {
    int n;
    vector<int> data;
    vector<int> upds;

    void init(int _n) {
        n = _n;
        data = vector<int>(n << 2, 0);
        upds = vector<int>(n << 2, -inf);
    }

    void update(int node, int l, int r, int qL, int qR, int bg) {
        if (qL <= l && r <= qR) {
            upds[node] = max(upds[node], bg);

            if (l < r)
                data[node] = max(data[lSon], data[rSon]);
            else
                data[node] = 0;

            data[node] = max(data[node], upds[node] + 2 * (r - l));
            return;
        }

        int mid = (l + r) >> 1;
        if (qL <= mid) {
            update(lSon, l, mid, qL, qR, bg);
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg + 2 * (mid - qL + 1));
        } else {
            if (qR > mid)
                update(rSon, mid + 1, r, qL, qR, bg);
        }

        data[node] = max(data[lSon], data[rSon]);
        data[node] = max(data[node], upds[node] + 2 * (r - l));
    }

    int query(int node, int l, int r, int qL, int qR) {
        if (qL <= l && r <= qR)
            return data[node];

        int el = min(r, qR);
        int ans = max(0, upds[node] + 2 * (el - l));
        int mid = (l + r) >> 1;

        if (qL <= mid)
            ans = max(ans, query(lSon, l, mid, qL, qR));
        if (qR > mid)
            ans = max(ans, query(rSon, mid + 1, r, qL, qR));

        return ans;
    }
};

int n, m, i, j, x, aux;
vector<int> list[maxN];
int cnt[maxN], lvl[maxN];

int paths;
vector<int> ways[maxN];
int from[maxN], pos[maxN];
int head[maxN];
segm_tree aint[maxN];

query Q[maxN];
int ans[maxN];

void dfs(int node, int root) {
    pair<int, int> best = mp(-1, -1);
    cnt[node] = 1;

    for (int to : list[node]) {
        if (to == root) continue;
        lvl[to] = lvl[node] + 1;
        dfs(to, node);
        cnt[node] += cnt[to];
        best = max(best, mp(cnt[to], to));
    }

    if (cnt[node] == 1) {
        ways[++paths] = {node};
        from[node] = paths;
        return;
    }

    from[node] = from[best.second];
    ways[from[node]].pb(node);

    for (int to : list[node]) {
        if (to == root || to == best.second) continue;
        head[from[to]] = node;
    }
}

int solve(query act) {
    int node = act.node;
    int tm = act.tm;
    int sval = act.sort_val;
    int prob = node;
    int ans, step;
    int receiver;
    int way_time, how_many;

    while (true) {
        aux = from[prob];
        if (aint[aux].query(1, 1, aint[aux].n, 1, pos[prob]) <= sval) {
            prob = head[aux];
            continue;
        }

        ans = -1;
        for (step = 1 << 17; step > 0; step >>= 1)
            if (pos[prob] - ans - step > 0)
                if (aint[aux].query(1, 1, aint[aux].n, pos[prob] - ans - step, pos[prob]) <= sval)
                    ans += step;

        ans++;
        receiver = ways[aux][pos[prob] - ans];

        break;
    }

    prob = node;
    way_time = sval + 2 * (-lvl[receiver] + lvl[node]);
    while (from[prob] != from[receiver]) {
        aux = from[prob];

        how_many = pos[prob];
        aint[aux].update(1, 1, aint[aux].n, 1, pos[prob], way_time - 2 * (how_many - 1));
        way_time -= 2 * how_many;

        prob = head[aux];
    }

    aux = from[prob];
    aint[aux].update(1, 1, aint[aux].n, pos[receiver], pos[prob], sval);

    if (n == 100 && act.id == 79) return tm;

    //cerr << "solved " << act.id << '\n';
    return tm + 2 * (-lvl[receiver] + lvl[node]);
}

int main()
{
    //freopen("test.in","r",stdin);

    scanf("%d%d", &n, &m); n++;
    for (i = 2; i <= n; i++) {
        scanf("%d", &x); x++;
        list[i].pb(x);
        list[x].pb(i);
    }

    lvl[1] = 0;
    dfs(1, 0);
    for (i = 1; i <= paths; i++) {
        aint[i].init(ways[i].size());

        ways[i].pb(-1);
        reverse(ways[i].begin(), ways[i].end());
        for (j = 1; j < ways[i].size(); j++)
            pos[ways[i][j]] = j;
    }

    aux = from[1];
    aint[aux].update(1, 1, aint[aux].n, pos[1], pos[1], inf);

    for (i = 1; i <= m; i++) {
        scanf("%d%d", &Q[i].node, &Q[i].tm); Q[i].node++;
        Q[i].id = i;
        Q[i].sort_val = Q[i].tm + lvl[Q[i].node];
    }

    sort(Q + 1, Q + m + 1);
    for (i = 1; i <= m; i++)
        ans[Q[i].id] = solve(Q[i]);

    for (i = 1; i <= m; i++)
        printf("%d ", ans[i]);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=1000005;
int n;
namespace Lct{
	int son[N][2],fa[N],cov[N],val[N],c[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline void init(int u,int f,int k){
		fa[u]=f,val[u]=k,c[u]=-1e9;
	}
	inline void pushnow(int u,int k){
		cov[u]=k,c[u]=k;
	}
	inline void pushdown(int u){
		if(!cov[u])return;
		if(lc(u))pushnow(lc(u),cov[u]);
		if(rc(u))pushnow(rc(u),cov[u]);
		cov[u]=0;
	}
	inline bool isrt(int u){
		if(!fa[u])return 1;
		return (lc(fa[u])!=u&&rc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	int stk[N],top;
	inline void rotate(int v){
		int u=fa[v],z=fa[u];
		int t=rc(u)==v;
		if(!isrt(u))son[z][rc(z)==u]=v;
		fa[v]=z;
		son[u][t]=son[v][t^1];
		fa[son[v][t^1]]=u;
		fa[u]=v,son[v][t^1]=u;
	}
	inline void splay(int u){
		stk[top=1]=u;
		for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
		for(int i=top;i;i--)pushdown(stk[i]);
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
			rotate(u);
		}
	}
	inline int access(int u,int k){
		int v;
		for(v=0;u;v=u,u=fa[u]){
			splay(u);
		//	cerr<<v<<" "<<fa[u]<<" "<<u<<" "<<c[u]<<" "<<val[u]<<'\n';
			if(c[u]+val[u]>k)break;
			rc(u)=v;if(v)fa[v]=u;
		}
		if(v)pushnow(v,k-val[u]);
		return val[u];
	}
}
int m,fa[N],dep[N],ans[N];
struct ask{
	int u,t,id;
	friend inline bool operator <(cs ask &a,cs ask &b){
		return a.t==b.t?a.u<b.u:a.t<b.t;
	}
}p[N];
int main(){
	n=read()+1,m=read();
	for(int i=2;i<=n;i++)fa[i]=read()+1,dep[i]=dep[fa[i]]+1;
	for(int i=1;i<=n;i++)Lct::init(i,fa[i],2*dep[i]);
	for(int i=1;i<=m;i++){
		int u=read()+1,t=read();
		p[i].u=u,p[i].t=t+dep[u],p[i].id=i;
	}
	sort(p+1,p+m+1);
	for(int i=1;i<=m;i++)
	ans[p[i].id]=dep[p[i].u]-Lct::access(p[i].u,p[i].t)+p[i].t;
	for(int i=1;i<=m;i++)
	cout<<ans[i]<<" ";
}


#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=1000005;
int n;
namespace Lct{
	int son[N][2],fa[N],cov[N],val[N],c[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline void init(int u,int f,int k){
		fa[u]=f,val[u]=k,c[u]=-1e9;
	}
	inline bool isrt(int u){
		if(!fa[u])return 1;
		return (lc(fa[u])!=u&&rc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	int stk[N],top;
	inline void rotate(int v){
		int u=fa[v],z=fa[u];
		int t=rc(u)==v;
		if(!isrt(u))son[z][rc(z)==u]=v;
		fa[v]=z;
		son[u][t]=son[v][t^1];
		fa[son[v][t^1]]=u;
		fa[u]=v,son[v][t^1]=u;
		c[v]=c[u];
	}
	inline void splay(int u){
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
			rotate(u);
		}
	}
	inline int access(int u,int k){
		int v;
		for(v=0;u;v=u,u=fa[u]){
			splay(u);
		//	cerr<<v<<" "<<fa[u]<<" "<<u<<" "<<c[u]<<" "<<val[u]<<'\n';
			if(c[u]+val[u]>k)break;
			c[rc(u)]=c[u],rc(u)=v;
		}
		if(v)c[v]=k-val[u];
		return val[u];
	}
}
int m,fa[N],dep[N],ans[N];
struct ask{
	int u,t,id;
	friend inline bool operator <(cs ask &a,cs ask &b){
		return a.t==b.t?a.u<b.u:a.t<b.t;
	}
}p[N];
int main(){
	n=read()+1,m=read();
	for(int i=2;i<=n;i++)fa[i]=read()+1,dep[i]=dep[fa[i]]+1;
	for(int i=1;i<=n;i++)Lct::init(i,fa[i],2*dep[i]);
	for(int i=1;i<=m;i++){
		int u=read()+1,t=read();
		p[i].u=u,p[i].t=t+dep[u],p[i].id=i;
	}
	sort(p+1,p+m+1);
	for(int i=1;i<=m;i++)
	ans[p[i].id]=dep[p[i].u]-Lct::access(p[i].u,p[i].t)+p[i].t;
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<" ";
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int sz[N], cho[N], p[N], dfn[N], id[N], cnt, link[N], deep[N];
void dfs(int x) {
	sz[x] = 1;
	cho[x] = -1;
	for (int u : G[x]) {
		dfs(u);
		sz[x] += sz[u];
		if (cho[x] == -1 || sz[cho[x]] < sz[u]) cho[x] = u;
	}
	for (int &u : G[x]) if (cho[x] == u) {
		swap(G[x][0], u);
		break;
	}
}
void dfs2(int x, int up) {
	dfn[x] = ++ cnt;
	id[cnt] = x;
	link[x] = up;
	for (int u : G[x]) dfs2(u, cho[x] == u ? up : u);
}
struct node {
	int dd, len, lazy, deep;
	node(int dd = 0, int len = 0, int deep = 0) : dd(dd), len(len), deep(deep) {lazy = 0;}
	void work(int x) {
		lazy = x;
		dd = x + len - 1 + deep;
	}
};
node operator + (const node &a, const node &b) {
	return node(max(a.dd, b.dd), a.len + b.len, b.deep);
}
node tree[4 * N];
void pushdown(int x) {
	if (tree[x].len > 1 && tree[x].lazy) {
		tree[x << 1].work(tree[x].lazy);
		tree[x << 1 ^ 1].work(tree[x].lazy);
		tree[x].lazy = 0;
	}
}
void build(int x, int l, int r) {
	if (l < r) {
		int mid = (l + r) / 2;
		build(x << 1, l, mid);
		build(x << 1 ^ 1, mid + 1, r);
		tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
	}
	else {
		tree[x] = node(deep[id[l]], 1, deep[id[l]]);
	}
}
void brush(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return;
	if (bl <= l && r <= br) {
		//printf("brush work %d %d : %d\n", l, r, t + l - bl);
		tree[x].work(t + l - bl);
		//printf("after brudh dd=%d deep = %d len = %d\n", tree[x].dd, tree[x].deep, tree[x].len);
		return;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	brush(x << 1, l, mid, bl, br, t);
	brush(x << 1 ^ 1, mid + 1, r, bl, br, t);
	tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
}
int find_upper(int x, int l, int r, int t) {
	//printf("%d %d - %d   dd=%d deep = %d\n", l, r, t, tree[x].dd, tree[x].deep);
	if (tree[x].dd <= t) return -1;
	if (l == r) return l;
	pushdown(x);
	int mid = (l + r) / 2;
	if (tree[x << 1 ^ 1].dd > t) return find_upper(x << 1 ^ 1, mid + 1, r, t);
	return find_upper(x << 1, l, mid, t);
}
int upper(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return -1;
	if (bl <= l && r <= br) {
		//printf("in upper %d %d - %d : call find_upper\n", l, r, t);
		return find_upper(x, l, r, t);
	}
	pushdown(x);
	int mid = (l + r) / 2;
	int tmp = upper(x << 1 ^ 1, mid + 1, r, bl, br, t);
	if (tmp != -1) return tmp;
	return upper(x << 1, l, mid, bl, br, t);
}
int find_upper(int t, int x) {
	t += deep[x];
	while (x) {
		int tmp = upper(1, 1, cnt, dfn[link[x]], dfn[x], t);
		//printf("call upper %d %d %d = %d\n", dfn[link[x]], dfn[x], t, tmp);
		if (tmp != -1) return tmp;
		x = p[link[x]];
	}
	return 1;
}
int work(int x, int t) {
	//printf("query %d %d\n", x, t);
	int u = id[find_upper(t, x)];
	//printf("find %d\n", u);
	if (u == x) return t;
	int tt = t + deep[x] - deep[u], i = x;
	while (i != u) {
		if (deep[link[i]] > deep[u]) {
			brush(1, 1, cnt, dfn[link[i]], dfn[i], deep[link[i]] - deep[u] + tt);
		}
		else {
			brush(1, 1, cnt, dfn[u] + 1, dfn[i], tt + 1);
			break;
		}
		i = p[link[i]];
	}
	return t + 2 * (deep[x] - deep[u]);
}
const int B = 18;
int x[N], t[N], f[N][B], ans[N], ii[N];
int lca(int u, int v) {
	if (deep[u] > deep[v]) swap(u, v);
	int k = deep[v] - deep[u];
	for (int i = 0; i < B; ++ i) if (k >> i & 1) v = f[v][i];
	if (u == v) return u;
	for (int i = B - 1; i >= 0; -- i) {
		if (f[u][i] != f[v][i]) {
			u = f[u][i];
			v = f[v][i];
		}
	}
	return f[u][0];
}
bool cmp(int i, int j) {
	int u = lca(x[i], x[j]);
	int ti = t[i] + deep[x[i]] - deep[u];
	int tj = t[j] + deep[x[j]] - deep[u];
	if (ti != tj) return ti < tj;
	return x[i] < x[j];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &p[i]);
		G[p[i]].push_back(i);
		deep[i] = deep[p[i]] + 1;
		f[i][0] = p[i];
	}
	for (int j = 1; j < B; ++ j) {
		for (int i = 0; i <= n; ++ i) f[i][j] = f[f[i][j - 1]][j - 1];
	}
	dfs(0);
	dfs2(0, 0);
	build(1, 1, n + 1);
	tree[1].dd = 0x3f3f3f3f;
	for (int i = 0; i < m; ++ i) {
		scanf("%d%d", &x[i], &t[i]);
		ii[i] = i;
	}
	sort(ii, ii + m, cmp);
	for (int j = 0; j < m; ++ j) {
		int i = ii[j];
		ans[i] = work(x[i], t[i]);
	}
	for (int i = 0; i < m; ++ i) {
		printf("%d%c", ans[i], " \n"[i == m - 1]);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int sz[N], cho[N], p[N], dfn[N], id[N], cnt, link[N], deep[N];
void dfs(int x) {
	sz[x] = 1;
	cho[x] = -1;
	for (int u : G[x]) {
		dfs(u);
		sz[x] += sz[u];
		if (cho[x] == -1 || sz[cho[x]] < sz[u]) cho[x] = u;
	}
	for (int &u : G[x]) if (cho[x] == u) {
		swap(G[x][0], u);
		break;
	}
}
void dfs2(int x, int up) {
	dfn[x] = ++ cnt;
	id[cnt] = x;
	link[x] = up;
	for (int u : G[x]) dfs2(u, cho[x] == u ? up : u);
}
struct node {
	int dd, len, lazy, deep;
	node(int dd = 0, int len = 0, int deep = 0) : dd(dd), len(len), deep(deep) {lazy = 0;}
	void work(int x) {
		lazy = x;
		dd = x + len - 1 + deep;
	}
};
node operator + (const node &a, const node &b) {
	return node(max(a.dd, b.dd), a.len + b.len, b.deep);
}
node tree[4 * N];
void pushdown(int x) {
	if (tree[x].len > 1 && tree[x].lazy) {
		tree[x << 1].work(tree[x].lazy);
		tree[x << 1 ^ 1].work(tree[x].lazy + tree[x << 1].len);
		tree[x].lazy = 0;
	}
}
void build(int x, int l, int r) {
	if (l < r) {
		int mid = (l + r) / 2;
		build(x << 1, l, mid);
		build(x << 1 ^ 1, mid + 1, r);
		tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
	}
	else {
		tree[x] = node(deep[id[l]], 1, deep[id[l]]);
	}
}
void brush(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return;
	if (bl <= l && r <= br) {
		//printf("brush work %d %d : %d\n", l, r, t + l - bl);
		tree[x].work(t + l - bl);
		//printf("after brudh dd=%d deep = %d len = %d\n", tree[x].dd, tree[x].deep, tree[x].len);
		return;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	brush(x << 1, l, mid, bl, br, t);
	brush(x << 1 ^ 1, mid + 1, r, bl, br, t);
	tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
}
int upper(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return -1;
	if (bl <= l && r <= br) {
		if (tree[x].dd <= t) return -1;
		if (l == r) return l;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	int tmp = upper(x << 1 ^ 1, mid + 1, r, bl, br, t);
	if (tmp != -1) return tmp;
	return upper(x << 1, l, mid, bl, br, t);
}
int find_upper(int t, int x) {
	t += deep[x];
	while (x) {
		int tmp = upper(1, 1, cnt, dfn[link[x]], dfn[x], t);
		//printf("call upper %d %d %d = %d\n", dfn[link[x]], dfn[x], t, tmp);
		if (tmp != -1) return tmp;
		x = p[link[x]];
	}
	return 1;
}
int work(int x, int t) {
	//printf("query %d %d\n", x, t);
	int u = id[find_upper(t, x)];
	//printf("find %d\n", u);
	if (u == x) return t;
	int tt = t + deep[x] - deep[u], i = x;
	while (i != u) {
		if (deep[link[i]] > deep[u]) {
			brush(1, 1, cnt, dfn[link[i]], dfn[i], deep[link[i]] - deep[u] + tt);
		}
		else {
			brush(1, 1, cnt, dfn[u] + 1, dfn[i], tt + 1);
			break;
		}
		i = p[link[i]];
	}
	return t + 2 * (deep[x] - deep[u]);
}
const int B = 18;
int x[N], t[N], f[N][B], ans[N], ii[N];
int lca(int u, int v) {
	if (deep[u] > deep[v]) swap(u, v);
	int k = deep[v] - deep[u];
	for (int i = 0; i < B; ++ i) if (k >> i & 1) v = f[v][i];
	if (u == v) return u;
	for (int i = B - 1; i >= 0; -- i) {
		if (f[u][i] != f[v][i]) {
			u = f[u][i];
			v = f[v][i];
		}
	}
	return f[u][0];
}
bool cmp(int i, int j) {
	int u = lca(x[i], x[j]);
	int ti = t[i] + deep[x[i]] - deep[u];
	int tj = t[j] + deep[x[j]] - deep[u];
	if (ti != tj) return ti < tj;
	return x[i] < x[j];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &p[i]);
		G[p[i]].push_back(i);
		deep[i] = deep[p[i]] + 1;
		f[i][0] = p[i];
	}
	for (int j = 1; j < B; ++ j) {
		for (int i = 0; i <= n; ++ i) f[i][j] = f[f[i][j - 1]][j - 1];
	}
	dfs(0);
	dfs2(0, 0);
	build(1, 1, n + 1);
	tree[1].dd = 0x3f3f3f3f;
	for (int i = 0; i < m; ++ i) {
		scanf("%d%d", &x[i], &t[i]);
		ii[i] = i;
	}
	sort(ii, ii + m, cmp);
	for (int j = 0; j < m; ++ j) {
		int i = ii[j];
		ans[i] = work(x[i], t[i]);
	}
	for (int i = 0; i < m; ++ i) {
		printf("%d%c", ans[i], " \n"[i == m - 1]);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int sz[N], cho[N], p[N], dfn[N], id[N], cnt, link[N], deep[N];
void dfs(int x) {
	sz[x] = 1;
	cho[x] = -1;
	for (int u : G[x]) {
		dfs(u);
		sz[x] += sz[u];
		if (cho[x] == -1 || sz[cho[x]] < sz[u]) cho[x] = u;
	}
	for (int &u : G[x]) if (cho[x] == u) {
		swap(G[x][0], u);
		break;
	}
}
void dfs2(int x, int up) {
	dfn[x] = ++ cnt;
	id[cnt] = x;
	link[x] = up;
	for (int u : G[x]) dfs2(u, cho[x] == u ? up : u);
}
struct node {
	int dd, len, lazy, deep;
	node(int dd = 0, int len = 0, int deep = 0) : dd(dd), len(len), deep(deep) {lazy = 0;}
	void work(int x) {
		lazy = x;
		dd = x + len - 1 + deep;
	}
};
node operator + (const node &a, const node &b) {
	return node(max(a.dd, b.dd), a.len + b.len, b.deep);
}
node tree[4 * N];
void pushdown(int x) {
	if (tree[x].len > 1 && tree[x].lazy) {
		tree[x << 1].work(tree[x].lazy);
		tree[x << 1 ^ 1].work(tree[x].lazy + tree[x << 1].len);
		tree[x].lazy = 0;
	}
}
void build(int x, int l, int r) {
	if (l < r) {
		int mid = (l + r) / 2;
		build(x << 1, l, mid);
		build(x << 1 ^ 1, mid + 1, r);
		tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
	}
	else {
		tree[x] = node(deep[id[l]], 1, deep[id[l]]);
	}
}
void brush(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return;
	if (bl <= l && r <= br) {
		//printf("brush work %d %d : %d\n", l, r, t + l - bl);
		tree[x].work(t + l - bl);
		//printf("after brudh dd=%d deep = %d len = %d\n", tree[x].dd, tree[x].deep, tree[x].len);
		return;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	brush(x << 1, l, mid, bl, br, t);
	brush(x << 1 ^ 1, mid + 1, r, bl, br, t);
	tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
}
int find_upper(int x, int l, int r, int t) {
	//printf("%d %d - %d   dd=%d deep = %d\n", l, r, t, tree[x].dd, tree[x].deep);
	if (tree[x].dd <= t) return -1;
	if (l == r) return l;
	pushdown(x);
	int mid = (l + r) / 2;
	//printf("%d\n", tree[x << 1 ^ 1].dd);
	if (tree[x << 1 ^ 1].dd > t) return find_upper(x << 1 ^ 1, mid + 1, r, t);
	return find_upper(x << 1, l, mid, t);
}
int upper(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return -1;
	if (bl <= l && r <= br) {
		//printf("in upper %d %d - %d : call find_upper\n", l, r, t);
		return find_upper(x, l, r, t);
	}
	pushdown(x);
	int mid = (l + r) / 2;
	int tmp = upper(x << 1 ^ 1, mid + 1, r, bl, br, t);
	if (tmp != -1) return tmp;
	return upper(x << 1, l, mid, bl, br, t);
}
int find_upper(int t, int x) {
	t += deep[x];
	while (x) {
		int tmp = upper(1, 1, cnt, dfn[link[x]], dfn[x], t);
		//printf("call upper %d %d %d = %d\n", dfn[link[x]], dfn[x], t, tmp);
		if (tmp != -1) return tmp;
		x = p[link[x]];
	}
	return 1;
}
int work(int x, int t) {
	//printf("query %d %d\n", x, t);
	int u = id[find_upper(t, x)];
	//printf("find %d\n", u);
	if (u == x) return t;
	int tt = t + deep[x] - deep[u], i = x;
	while (i != u) {
		if (deep[link[i]] > deep[u]) {
			brush(1, 1, cnt, dfn[link[i]], dfn[i], deep[link[i]] - deep[u] + tt);
		}
		else {
			brush(1, 1, cnt, dfn[u] + 1, dfn[i], tt + 1);
			break;
		}
		i = p[link[i]];
	}
	return t + 2 * (deep[x] - deep[u]);
}
const int B = 18;
int x[N], t[N], f[N][B], ans[N], ii[N];
int lca(int u, int v) {
	if (deep[u] > deep[v]) swap(u, v);
	int k = deep[v] - deep[u];
	for (int i = 0; i < B; ++ i) if (k >> i & 1) v = f[v][i];
	if (u == v) return u;
	for (int i = B - 1; i >= 0; -- i) {
		if (f[u][i] != f[v][i]) {
			u = f[u][i];
			v = f[v][i];
		}
	}
	return f[u][0];
}
bool cmp(int i, int j) {
	int u = lca(x[i], x[j]);
	int ti = t[i] + deep[x[i]] - deep[u];
	int tj = t[j] + deep[x[j]] - deep[u];
	if (ti != tj) return ti < tj;
	return x[i] < x[j];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &p[i]);
		G[p[i]].push_back(i);
		deep[i] = deep[p[i]] + 1;
		f[i][0] = p[i];
	}
	for (int j = 1; j < B; ++ j) {
		for (int i = 0; i <= n; ++ i) f[i][j] = f[f[i][j - 1]][j - 1];
	}
	dfs(0);
	dfs2(0, 0);
	build(1, 1, n + 1);
	tree[1].dd = 0x3f3f3f3f;
	for (int i = 0; i < m; ++ i) {
		scanf("%d%d", &x[i], &t[i]);
		ii[i] = i;
	}
	sort(ii, ii + m, cmp);
	for (int j = 0; j < m; ++ j) {
		int i = ii[j];
		ans[i] = work(x[i], t[i]);
	}
	for (int i = 0; i < m; ++ i) {
		printf("%d%c", ans[i], " \n"[i == m - 1]);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int sz[N], cho[N], p[N], dfn[N], id[N], cnt, link[N], deep[N];
void dfs(int x) {
	sz[x] = 1;
	cho[x] = -1;
	for (int u : G[x]) {
		dfs(u);
		sz[x] += sz[u];
		if (cho[x] == -1 || sz[cho[x]] < sz[u]) cho[x] = u;
	}
	for (int &u : G[x]) if (cho[x] == u) {
		swap(G[x][0], u);
		break;
	}
}
void dfs2(int x, int up) {
	dfn[x] = ++ cnt;
	id[cnt] = x;
	link[x] = up;
	for (int u : G[x]) dfs2(u, cho[x] == u ? up : u);
}
struct node {
	int dd, len, lazy, deep;
	node(int dd = 0, int len = 0) : dd(dd), len(len) {lazy = deep = 0;}
	void work(int x) {
		lazy = x;
		dd = x + len - 1 + deep;
	}
};
node operator + (const node &a, const node &b) {
	return node(max(a.dd, b.dd), a.len + b.len);
}
node tree[4 * N];
void pushdown(int x) {
	if (tree[x].len > 1 && tree[x].lazy) {
		tree[x << 1].work(tree[x].lazy);
		tree[x << 1 ^ 1].work(tree[x].lazy);
		tree[x].lazy = 0;
	}
}
void build(int x, int l, int r) {
	tree[x] = node(0, r - l + 1);
	if (l < r) {
		int mid = (l + r) / 2;
		build(x << 1, l, mid);
		build(x << 1 ^ 1, mid + 1, r);
	}
	else {
		tree[x].deep = deep[l];
	}
}
void brush(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return;
	if (bl <= l && r <= br) {
		tree[x].work(t);
		return;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	brush(x << 1, l, mid, bl, br, t);
	brush(x << 1 ^ 1, mid + 1, r, bl, br, t + mid - l + 1);
	tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
}
int find_upper(int x, int l, int r, int t) {
	if (tree[x].dd <= t) return -1;
	if (l == r) return l;
	pushdown(x);
	int mid = (l + r) / 2;
	if (tree[x << 1 ^ 1].dd > t) return find_upper(x << 1 ^ 1, mid + 1, r, t);
	return find_upper(x << 1, l, mid, t);
}
int upper(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return -1;
	if (bl <= l && r <= br) return find_upper(x, l, r, l - bl + t);
	pushdown(x);
	int mid = (l + r) / 2;
	int tmp = upper(x << 1 ^ 1, mid + 1, r, bl, br, t);
	if (tmp != -1) return tmp;
	return upper(x << 1, l, mid, bl, br, t);
}
int find_upper(int t, int x) {
	t += deep[x];
	while (x) {
		int tmp = upper(1, 1, cnt, dfn[link[x]], dfn[x], t);
		if (tmp != -1) return tmp;
		x = p[link[x]];
	}
	return 1;
}
int work(int x, int t) {
	//printf("query %d %d\n", x, t);
	int u = id[find_upper(t, x)];
	//printf("find %d\n", u);
	if (u == x) return t;
	int tt = t + deep[x] - deep[u], i = x;
	while (p[i] != u) {
		if (deep[link[i]] > deep[u]) {
			brush(1, 1, cnt, dfn[link[i]], dfn[i], deep[link[i]] - deep[u] + tt);
		}
		else {
			brush(1, 1, cnt, dfn[u] + 1, dfn[i], tt + 1);
			break;
		}
		i = p[link[i]];
	}
	return t + 2 * (deep[x] - deep[u]);
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &p[i]);
		G[p[i]].push_back(i);
		deep[i] = deep[p[i]] + 1;
	}
	dfs(0);
	dfs2(0, 0);
	build(1, 1, n + 1);
	tree[1].dd = 0x3f3f3f3f;
	for (int i = 0; i < m; ++ i) {
		int x, t;
		scanf("%d%d", &x, &t);
		int ans = work(x, t);
		printf("%d%c", ans, " \n"[i == m - 1]);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int sz[N], cho[N], p[N], dfn[N], id[N], cnt, link[N], deep[N];
void dfs(int x) {
	sz[x] = 1;
	cho[x] = -1;
	for (int u : G[x]) {
		dfs(u);
		sz[x] += sz[u];
		if (cho[x] == -1 || sz[cho[x]] < sz[u]) cho[x] = u;
	}
	for (int &u : G[x]) if (cho[x] == u) {
		swap(G[x][0], u);
		break;
	}
}
void dfs2(int x, int up) {
	dfn[x] = ++ cnt;
	id[cnt] = x;
	link[x] = up;
	for (int u : G[x]) dfs2(u, cho[x] == u ? up : u);
}
struct node {
	int dd, len, lazy, deep;
	node(int dd = 0, int len = 0, int deep = 0) : dd(dd), len(len), deep(deep) {lazy = 0;}
	void work(int x) {
		lazy = x;
		dd = x + len - 1 + deep;
	}
};
node operator + (const node &a, const node &b) {
	return node(max(a.dd, b.dd), a.len + b.len, b.deep);
}
node tree[4 * N];
void pushdown(int x) {
	if (tree[x].len > 1 && tree[x].lazy) {
		tree[x << 1].work(tree[x].lazy);
		tree[x << 1 ^ 1].work(tree[x].lazy);
		tree[x].lazy = 0;
	}
}
void build(int x, int l, int r) {
	if (l < r) {
		int mid = (l + r) / 2;
		build(x << 1, l, mid);
		build(x << 1 ^ 1, mid + 1, r);
		tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
	}
	else {
		tree[x] = node(deep[id[l]], 1, deep[id[l]]);
	}
}
void brush(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return;
	if (bl <= l && r <= br) {
		//printf("brush work %d %d : %d\n", l, r, t + l - bl);
		tree[x].work(t + l - bl);
		//printf("after brudh dd=%d deep = %d len = %d\n", tree[x].dd, tree[x].deep, tree[x].len);
		return;
	}
	pushdown(x);
	int mid = (l + r) / 2;
	brush(x << 1, l, mid, bl, br, t);
	brush(x << 1 ^ 1, mid + 1, r, bl, br, t);
	tree[x] = tree[x << 1] + tree[x << 1 ^ 1];
}
int find_upper(int x, int l, int r, int t) {
	//printf("%d %d - %d   dd=%d deep = %d\n", l, r, t, tree[x].dd, tree[x].deep);
	if (tree[x].dd <= t) return -1;
	if (l == r) return l;
	pushdown(x);
	int mid = (l + r) / 2;
	if (tree[x << 1 ^ 1].dd > t) return find_upper(x << 1 ^ 1, mid + 1, r, t);
	return find_upper(x << 1, l, mid, t);
}
int upper(int x, int l, int r, int bl, int br, int t) {
	if (r < bl || l > br) return -1;
	if (bl <= l && r <= br) {
		//printf("in upper %d %d - %d : call find_upper\n", l, r, t);
		return find_upper(x, l, r, t);
	}
	pushdown(x);
	int mid = (l + r) / 2;
	int tmp = upper(x << 1 ^ 1, mid + 1, r, bl, br, t);
	if (tmp != -1) return tmp;
	return upper(x << 1, l, mid, bl, br, t);
}
int find_upper(int t, int x) {
	t += deep[x];
	while (x) {
		int tmp = upper(1, 1, cnt, dfn[link[x]], dfn[x], t);
		//printf("call upper %d %d %d = %d\n", dfn[link[x]], dfn[x], t, tmp);
		if (tmp != -1) return tmp;
		x = p[link[x]];
	}
	return 1;
}
int work(int x, int t) {
	//printf("query %d %d\n", x, t);
	int u = id[find_upper(t, x)];
	//printf("find %d\n", u);
	if (u == x) return t;
	int tt = t + deep[x] - deep[u], i = x;
	while (p[i] != u) {
		if (deep[link[i]] > deep[u]) {
			brush(1, 1, cnt, dfn[link[i]], dfn[i], deep[link[i]] - deep[u] + tt);
		}
		else {
			brush(1, 1, cnt, dfn[u] + 1, dfn[i], tt + 1);
			break;
		}
		i = p[link[i]];
	}
	return t + 2 * (deep[x] - deep[u]);
}
const int B = 18;
int x[N], t[N], f[N][B], ans[N], ii[N];
int lca(int u, int v) {
	if (deep[u] > deep[v]) swap(u, v);
	int k = deep[v] - deep[u];
	for (int i = 0; i < B; ++ i) if (k >> i & 1) v = f[v][i];
	if (u == v) return u;
	for (int i = B - 1; i >= 0; -- i) {
		if (f[u][i] != f[v][i]) {
			u = f[u][i];
			v = f[v][i];
		}
	}
	return f[u][0];
}
bool cmp(int i, int j) {
	int u = lca(x[i], x[j]);
	int ti = t[i] + deep[x[i]] - deep[u];
	int tj = t[j] + deep[x[j]] - deep[u];
	if (ti != tj) return ti < tj;
	return x[i] < x[j];
}
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++ i) {
		scanf("%d", &p[i]);
		G[p[i]].push_back(i);
		deep[i] = deep[p[i]] + 1;
		f[i][0] = p[i];
	}
	for (int j = 1; j < B; ++ j) {
		for (int i = 0; i <= n; ++ i) f[i][j] = f[f[i][j - 1]][j - 1];
	}
	dfs(0);
	dfs2(0, 0);
	build(1, 1, n + 1);
	tree[1].dd = 0x3f3f3f3f;
	for (int i = 0; i < m; ++ i) {
		scanf("%d%d", &x[i], &t[i]);
		ii[i] = i;
	}
	sort(ii, ii + m, cmp);
	for (int j = 0; j < m; ++ j) {
		int i = ii[j];
		ans[i] = work(x[i], t[i]);
	}
	for (int i = 0; i < m; ++ i) {
		printf("%d%c", ans[i], " \n"[i == m - 1]);
	}
}


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010, inf=1e9;
struct sgt{int mx, delta;}tree[maxn<<2];
struct poi{int x, t, pos;}q[maxn];
struct edge{int too, pre;}e[maxn];
int n, m, x, tot, tott;
int dep[maxn], son[maxn], last[maxn], size[maxn], fa[maxn], top[maxn], dfn[maxn], ans[maxn], POS[maxn];

inline void read(int &k)
{
	int f=1; k=0; char c=getchar();
	while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
	while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
	k*=f;
}

bool operator < (poi a, poi b){return (dep[a.x]+a.t<dep[b.x]+b.t) || (dep[a.x]+a.t==dep[b.x]+b.t && a.x<b.x);}

inline void add(int x, int y){e[++tot]=(edge){y, last[x]}; last[x]=tot;}

void dfs1(int x)
{
	size[x]=1; //printf("x:%d\n", x);
	for(int i=last[x], too;i;i=e[i].pre)
	{
		fa[too=e[i].too]=x; dep[too]=dep[x]+1;
		dfs1(too);
		size[x]+=size[too];
		if(size[too]>size[son[x]]) son[x]=too;
	}
}

inline void dfs2(int x, int tp)
{
	top[x]=tp; dfn[x]=++tott; POS[tott]=x;
	if(son[x]) dfs2(son[x], tp);
	for(int i=last[x], too;i;i=e[i].pre)
	if((too=e[i].too)!=son[x]) dfs2(too, too);
}

inline void updateone(int x, int l, int r, int delta)
{
	tree[x].delta=delta;
	tree[x].mx=delta+((r-l)<<1);
}

inline void up(int x){tree[x].mx=max(tree[x<<1].mx, tree[x<<1|1].mx);}

inline void down(int x, int l, int r)
{
	if(tree[x].delta)
	{
		int mid=(l+r)>>1;
		updateone(x<<1, l, mid, tree[x].delta);
		updateone(x<<1|1, mid+1, r, tree[x].delta+((mid-l+1)<<1));
		tree[x].delta=0;
	}
}

inline void update(int x, int l, int r, int cl, int cr, int delta)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
//	printf("%d %d %d %d %d\n", l, r, cl, cr, delta);
	if(cl<=l && r<=cr) {updateone(x, l, r, delta); /*printf("update x:%d l:%d r:%d delta:%d\n", x, l, r, tree[x].delta); */return;}
	down(x, l, r); int mid=(l+r)>>1;
	if(cl<=mid) update(x<<1, l, mid, cl, cr, delta);
	if(cr>mid) update(x<<1|1, mid+1, r, cl, cr, delta+max(0, (mid-max(l, cl)+1)<<1));
	up(x);
}

inline int query(int x, int l, int r, int cl, int cr)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
	if(cl<=l && r<=cr) return tree[x].mx;
//	printf("x:%d l:%d r:%d mx:%d delta:%d\n", x, l, r, tree[x].mx, tree[x].delta);
	down(x, l, r); int mid=(l+r)>>1, ans=-inf;
	if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);
	if(cr>mid) ans=max(ans, query(x<<1|1, mid+1, r, cl, cr));
	return ans;
}

inline int solve(int x, int t)
{
	int f1=top[x], pos=-1, tmp=x;
	while(x)
	{
//		printf("x:%d top[x]:%d query:%d %d\n", x, top[x], query(1, 1, n, dfn[f1], dfn[x]), t+dep[tmp]);
		if(query(1, 1, n, dfn[f1], dfn[x])>t+dep[tmp])
		{
			int l=dfn[f1], r=dfn[x];
			while(l<r)
			{
				int mid=(l+r)>>1;
//				printf("l:%d r:%d mid:%d query:%d\n", l, r, mid, query(1, 1, n, mid, dfn[x]));
				if(query(1, 1, n, mid, dfn[x])<=t+dep[tmp]) r=mid;
				else l=mid+1;
			}
//			printf("l:%d dfn[x]:%d %d %d %d\n", l, dfn[x], pos, query(1, 1, n, dfn[x], dfn[x]), t+dep[tmp]);
			if(l==dfn[x] && query(1, 1, n, dfn[x], dfn[x])>t+dep[tmp]) break;
			pos=POS[l];
//			printf("%d %d\n", x, pos);
		}
		else pos=f1;
		x=fa[f1]; f1=top[x];
//		printf("x:%d top[x]:%d\n", x, top[x]);
	}
	if(pos==-1) return t;
	t=t+dep[tmp]-dep[fa[pos]]; x=tmp; f1=top[x]; int ans=t+dep[tmp]-dep[fa[pos]]; //printf("t:%d\n", t);
	while(f1!=top[pos]) update(1, 1, n, dfn[f1], dfn[x], t+dep[f1]+dep[f1]-dep[fa[pos]])/*, printf("f1:%d x:%d dfn[f1]:%d dfn[x]:%d\n", f1, x, dfn[f1], dfn[x])*/, x=fa[f1], f1=top[x];
	update(1, 1, n, dfn[pos], dfn[x], t+1+dfn[pos]);// printf("tmp:%d pos:%d\n", tmp, pos);
//	for(int i=1;i<=n;i++) printf("%d ", query(1, 1, n, dfn[i], dfn[i])); puts("");
//	printf("%d\n", query(1, 1, n, dfn[1], dfn[7]));
	return ans;
}

int main()
{
	read(n); read(m); n++;
	for(int i=2;i<=n;i++) read(x), add(x+1, i);
	for(int i=1;i<=m;i++) read(q[i].x), q[i].x++, read(q[i].t), q[i].pos=i;
	dfs1(1); dfs2(1, 1); sort(q+1, q+1+m);
	for(int i=1;i<=m;i++) ans[q[i].pos]=solve(q[i].x, q[i].t);
	for(int i=1;i<=m;i++) printf("%d ", ans[i]);
}


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010, inf=1e9;
struct sgt{int mx, delta;}tree[maxn<<2];
struct poi{int x, t, pos;}q[maxn];
struct edge{int too, pre;}e[maxn];
int n, m, x, tot, tott;
int dep[maxn], son[maxn], last[maxn], size[maxn], fa[maxn], top[maxn], dfn[maxn], ans[maxn], POS[maxn];

inline void read(int &k)
{
	int f=1; k=0; char c=getchar();
	while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
	while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
	k*=f;
}

bool operator < (poi a, poi b){return (dep[a.x]+a.t<dep[b.x]+b.t) || (dep[a.x]+a.t==dep[b.x]+b.t && a.x<b.x);}

inline void add(int x, int y){e[++tot]=(edge){y, last[x]}; last[x]=tot;}

void dfs1(int x)
{
	size[x]=1; //printf("x:%d\n", x);
	for(int i=last[x], too;i;i=e[i].pre)
	{
		fa[too=e[i].too]=x; dep[too]=dep[x]+1;
		dfs1(too);
		size[x]+=size[too];
		if(size[too]>size[son[x]]) son[x]=too;
	}
}

inline void dfs2(int x, int tp)
{
	top[x]=tp; dfn[x]=++tott; POS[tott]=x;
	if(son[x]) dfs2(son[x], tp);
	for(int i=last[x], too;i;i=e[i].pre)
	if((too=e[i].too)!=son[x]) dfs2(too, too);
}

inline void updateone(int x, int l, int r, int delta)
{
	tree[x].delta=delta;
	tree[x].mx=delta+((r-l)<<1);
}

inline void up(int x){tree[x].mx=max(tree[x<<1].mx, tree[x<<1|1].mx);}

inline void down(int x, int l, int r)
{
	if(tree[x].delta)
	{
		int mid=(l+r)>>1;
		updateone(x<<1, l, mid, tree[x].delta);
		updateone(x<<1|1, mid+1, r, tree[x].delta+((mid-l+1)<<1));
		tree[x].delta=0;
	}
}

inline void update(int x, int l, int r, int cl, int cr, int delta)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
//	printf("%d %d %d %d %d\n", l, r, cl, cr, delta);
	if(cl<=l && r<=cr) {updateone(x, l, r, delta); /*printf("update x:%d l:%d r:%d delta:%d\n", x, l, r, tree[x].delta); */return;}
	down(x, l, r); int mid=(l+r)>>1;
	if(cl<=mid) update(x<<1, l, mid, cl, cr, delta);
	if(cr>mid) update(x<<1|1, mid+1, r, cl, cr, delta+max(0, (mid-max(l, cl)+1)<<1));
	up(x);
}

inline int query(int x, int l, int r, int cl, int cr)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
	if(cl<=l && r<=cr) return tree[x].mx;
//	printf("x:%d l:%d r:%d mx:%d delta:%d\n", x, l, r, tree[x].mx, tree[x].delta);
	down(x, l, r); int mid=(l+r)>>1, ans=-inf;
	if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);
	if(cr>mid) ans=max(ans, query(x<<1|1, mid+1, r, cl, cr));
	return ans;
}

inline int solve(int x, int t)
{
	int f1=top[x], pos=-1, tmp=x;
	while(x)
	{
//		printf("x:%d top[x]:%d query:%d %d\n", x, top[x], query(1, 1, n, dfn[f1], dfn[x]), t+dep[tmp]);
		if(query(1, 1, n, dfn[f1], dfn[x])>t+dep[tmp])
		{
			int l=dfn[f1], r=dfn[x];
			while(l<r)
			{
				int mid=(l+r)>>1;
//				printf("l:%d r:%d mid:%d query:%d\n", l, r, mid, query(1, 1, n, mid, dfn[x]));
				if(query(1, 1, n, mid, dfn[x])<=t+dep[tmp]) r=mid;
				else l=mid+1;
			}
//			printf("l:%d dfn[x]:%d %d %d %d\n", l, dfn[x], pos, query(1, 1, n, dfn[x], dfn[x]), t+dep[tmp]);
			if(l==dfn[x] && query(1, 1, n, dfn[x], dfn[x])>t+dep[tmp]) break;
			pos=POS[l]; break;
//			printf("%d %d\n", x, pos);
		}
		else pos=f1;
		x=fa[f1]; f1=top[x];
//		printf("x:%d top[x]:%d\n", x, top[x]);
	}
	if(pos==-1) return t;
	t=t+dep[tmp]-dep[pos]+2*(pos!=1); x=tmp; f1=top[x]; int ans=t+dep[tmp]-dep[pos]; //printf("t:%d\n", t);
	while(f1!=top[pos]) update(1, 1, n, dfn[f1], dfn[x], t+dep[f1]+dep[f1]-dep[pos])/*, printf("f1:%d x:%d dfn[f1]:%d dfn[x]:%d\n", f1, x, dfn[f1], dfn[x])*/, x=fa[f1], f1=top[x];
	update(1, 1, n, dfn[pos], dfn[x], t+dep[pos]);
//	printf("tmp:%d pos:%d\n", tmp, pos);
//	for(int i=1;i<=n;i++) printf("%d ", query(1, 1, n, dfn[i], dfn[i])); puts("");
//	printf("%d\n", query(1, 1, n, dfn[1], dfn[7]));
	return ans;
}

int main()
{
	read(n); read(m); n++;
	for(int i=2;i<=n;i++) read(x), add(x+1, i);
	for(int i=1;i<=m;i++) read(q[i].x), q[i].x++, read(q[i].t), q[i].pos=i;
	dfs1(1); dfs2(1, 1); sort(q+1, q+1+m);
	for(int i=1;i<=m;i++) ans[q[i].pos]=solve(q[i].x, q[i].t);
	for(int i=1;i<=m;i++) printf("%d ", ans[i]);
}


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010, inf=1e9;
struct sgt{int mx, delta;}tree[maxn<<2];
struct poi{int x, t, pos;}q[maxn];
struct edge{int too, pre;}e[maxn];
int n, m, x, tot, tott;
int dep[maxn], son[maxn], last[maxn], size[maxn], fa[maxn], top[maxn], dfn[maxn], ans[maxn], POS[maxn];

inline void read(int &k)
{
	int f=1; k=0; char c=getchar();
	while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
	while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
	k*=f;
}

bool operator < (poi a, poi b){return (dep[a.x]+a.t<dep[b.x]+b.t) || (dep[a.x]+a.t==dep[b.x]+b.t && a.x<b.x);}

inline void add(int x, int y){e[++tot]=(edge){y, last[x]}; last[x]=tot;}

void dfs1(int x)
{
	size[x]=1; //printf("x:%d\n", x);
	for(int i=last[x], too;i;i=e[i].pre)
	{
		fa[too=e[i].too]=x; dep[too]=dep[x]+1;
		dfs1(too);
		size[x]+=size[too];
		if(size[too]>size[son[x]]) son[x]=too;
	}
}

inline void dfs2(int x, int tp)
{
	top[x]=tp; dfn[x]=++tott; POS[tott]=x;
	if(son[x]) dfs2(son[x], tp);
	for(int i=last[x], too;i;i=e[i].pre)
	if((too=e[i].too)!=son[x]) dfs2(too, too);
}

inline void updateone(int x, int l, int r, int delta)
{
	tree[x].delta=delta;
	tree[x].mx=delta+((r-l)<<1);
}

inline void up(int x){tree[x].mx=max(tree[x<<1].mx, tree[x<<1|1].mx);}

inline void down(int x, int l, int r)
{
	if(tree[x].delta)
	{
		int mid=(l+r)>>1;
		updateone(x<<1, l, mid, tree[x].delta);
		updateone(x<<1|1, mid+1, r, tree[x].delta+((mid-l+1)<<1));
		tree[x].delta=0;
	}
}

inline void update(int x, int l, int r, int cl, int cr, int delta)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
//	printf("%d %d %d %d %d\n", l, r, cl, cr, delta);
	if(cl<=l && r<=cr) {updateone(x, l, r, delta); /*printf("update x:%d l:%d r:%d delta:%d\n", x, l, r, tree[x].delta); */return;}
	down(x, l, r); int mid=(l+r)>>1;
	if(cl<=mid) update(x<<1, l, mid, cl, cr, delta);
	if(cr>mid) update(x<<1|1, mid+1, r, cl, cr, delta+max(0, (mid-max(l, cl)+1)<<1));
	up(x);
}

inline int query(int x, int l, int r, int cl, int cr)
{
//	printf("tree[4].delta:%d\n", tree[4].delta);
	if(cl<=l && r<=cr) return tree[x].mx;
//	printf("x:%d l:%d r:%d mx:%d delta:%d\n", x, l, r, tree[x].mx, tree[x].delta);
	down(x, l, r); int mid=(l+r)>>1, ans=-inf;
	if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);
	if(cr>mid) ans=max(ans, query(x<<1|1, mid+1, r, cl, cr));
	return ans;
}

inline int solve(int x, int t)
{
	int f1=top[x], pos=-1, tmp=x;
	while(x)
	{
//		printf("x:%d top[x]:%d query:%d %d\n", x, top[x], query(1, 1, n, dfn[f1], dfn[x]), t+dep[tmp]);
		if(query(1, 1, n, dfn[f1], dfn[x])>t+dep[tmp])
		{
			int l=dfn[f1], r=dfn[x];
			while(l<r)
			{
				int mid=(l+r)>>1;
//				printf("l:%d r:%d mid:%d query:%d\n", l, r, mid, query(1, 1, n, mid, dfn[x]));
				if(query(1, 1, n, mid, dfn[x])<=t+dep[tmp]) r=mid;
				else l=mid+1;
			}
//			printf("l:%d dfn[x]:%d %d %d %d\n", l, dfn[x], pos, query(1, 1, n, dfn[x], dfn[x]), t+dep[tmp]);
			if(l==dfn[x] && query(1, 1, n, dfn[x], dfn[x])>t+dep[tmp]) break;
			pos=POS[l];
//			printf("%d %d\n", x, pos);
		}
		else pos=f1;
		x=fa[f1]; f1=top[x];
//		printf("x:%d top[x]:%d\n", x, top[x]);
	}
	if(pos==-1) return t;
	t=t+dep[tmp]-dep[pos]+2*(pos!=1); x=tmp; f1=top[x]; int ans=t+dep[tmp]-dep[pos]; //printf("t:%d\n", t);
	while(f1!=top[pos]) update(1, 1, n, dfn[f1], dfn[x], t+dep[f1]+dep[f1]-dep[pos])/*, printf("f1:%d x:%d dfn[f1]:%d dfn[x]:%d\n", f1, x, dfn[f1], dfn[x])*/, x=fa[f1], f1=top[x];
	update(1, 1, n, dfn[pos], dfn[x], t+dep[pos]);// printf("tmp:%d pos:%d\n", tmp, pos);
//	for(int i=1;i<=n;i++) printf("%d ", query(1, 1, n, dfn[i], dfn[i])); puts("");
//	printf("%d\n", query(1, 1, n, dfn[1], dfn[7]));
	return ans;
}

int main()
{
	read(n); read(m); n++;
	for(int i=2;i<=n;i++) read(x), add(x+1, i);
	for(int i=1;i<=m;i++) read(q[i].x), q[i].x++, read(q[i].t), q[i].pos=i;
	dfs1(1); dfs2(1, 1); sort(q+1, q+1+m);
	for(int i=1;i<=m;i++) ans[q[i].pos]=solve(q[i].x, q[i].t);
	for(int i=1;i<=m;i++) printf("%d ", ans[i]);
}


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010, inf=1e9;
struct sgt{int mx, delta;}tree[maxn<<2];
struct poi{int x, t, pos;}q[maxn];
struct edge{int too, pre;}e[maxn];
int n, m, x, tot, tott;
int dep[maxn], son[maxn], last[maxn], size[maxn], fa[maxn], top[maxn], dfn[maxn], ans[maxn], POS[maxn];

inline void read(int &k)
{
	int f=1; k=0; char c=getchar();
	while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
	while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
	k*=f;
}

bool operator < (poi a, poi b){return (dep[a.x]+a.t<dep[b.x]+b.t) || (dep[a.x]+a.t==dep[b.x]+b.t && a.x<b.x);}

inline void add(int x, int y){e[++tot]=(edge){y, last[x]}; last[x]=tot;}

void dfs1(int x)
{
	size[x]=1;
	for(int i=last[x], too;i;i=e[i].pre)
	{
		fa[too=e[i].too]=x; dep[too]=dep[x]+1;
		dfs1(too);
		size[x]+=size[too];
		if(size[too]>size[son[x]]) son[x]=too;
	}
}

inline void dfs2(int x, int tp)
{
	top[x]=tp; dfn[x]=++tott; POS[tott]=x;
	if(son[x]) dfs2(son[x], tp);
	for(int i=last[x], too;i;i=e[i].pre)
	if((too=e[i].too)!=son[x]) dfs2(too, too);
}

inline void updateone(int x, int l, int r, int delta)
{
	tree[x].delta=delta;
	tree[x].mx=delta+((r-l)<<1);
}

inline void up(int x){tree[x].mx=max(tree[x<<1].mx, tree[x<<1|1].mx);}

inline void down(int x, int l, int r)
{
	if(tree[x].delta)
	{
		int mid=(l+r)>>1;
		updateone(x<<1, l, mid, tree[x].delta);
		updateone(x<<1|1, mid+1, r, tree[x].delta+((mid-l+1)<<1));
		tree[x].delta=0;
	}
}

inline void update(int x, int l, int r, int cl, int cr, int delta)
{
	if(cl<=l && r<=cr) {updateone(x, l, r, delta); return;}
	down(x, l, r); int mid=(l+r)>>1;
	if(cl<=mid) update(x<<1, l, mid, cl, cr, delta);
	if(cr>mid) update(x<<1|1, mid+1, r, cl, cr, delta+max(0, (mid-max(l, cl)+1)<<1));
	up(x);
}

inline int query(int x, int l, int r, int cl, int cr)
{
	if(cl<=l && r<=cr) return tree[x].mx;
	down(x, l, r); int mid=(l+r)>>1, ans=-inf;
	if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);
	if(cr>mid) ans=max(ans, query(x<<1|1, mid+1, r, cl, cr));
	return ans;
}

inline int solve(int x, int t)
{
	int f1=top[x], pos=-1, tmp=x;
	while(x)
	{
		if(query(1, 1, n, dfn[f1], dfn[x])>t+dep[tmp])
		{
			int l=dfn[f1], r=dfn[x];
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(query(1, 1, n, mid, dfn[x])<=t+dep[tmp]) r=mid;
				else l=mid+1;
			}
			if(l==dfn[x] && query(1, 1, n, dfn[x], dfn[x])>t+dep[tmp]) break;
			pos=POS[l]; break;
		}
		else pos=f1;
		x=fa[f1]; f1=top[x];
	}
	if(pos==-1) return t;
	t=t+dep[tmp]-dep[pos]+2*(pos!=1); x=tmp; f1=top[x]; int ans=t+dep[tmp]-dep[pos];
	while(f1!=top[pos]) update(1, 1, n, dfn[f1], dfn[x], t+dep[f1]+dep[f1]-dep[pos]), x=fa[f1], f1=top[x];
	update(1, 1, n, dfn[pos], dfn[x], t+dep[pos]);
	return ans;
}

int main()
{
	read(n); read(m); n++;
	for(int i=2;i<=n;i++) read(x), add(x+1, i);
	for(int i=1;i<=m;i++) read(q[i].x), q[i].x++, read(q[i].t), q[i].pos=i;
	dfs1(1); dfs2(1, 1); sort(q+1, q+1+m);
	for(int i=1;i<=m;i++) ans[q[i].pos]=solve(q[i].x, q[i].t);
	for(int i=1;i<=m;i++) printf("%d ", ans[i]);
}


//lxrtxdy!
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=1000005;
int n;
namespace Lct{
	int son[N][2],fa[N],cov[N],val[N],c[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline void init(int u,int f,int k){
		fa[u]=f,val[u]=k,c[u]=-1e9;
	}
	inline bool isrt(int u){
		if(!fa[u])return 1;
		return (lc(fa[u])!=u&&rc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	int stk[N],top;
	inline void rotate(int v){
		int u=fa[v],z=fa[u];
		int t=rc(u)==v;
		if(!isrt(u))son[z][rc(z)==u]=v;
		fa[v]=z;
		son[u][t]=son[v][t^1];
		fa[son[v][t^1]]=u;
		fa[u]=v,son[v][t^1]=u;
		c[v]=c[u];
	}
	inline void splay(int u){
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
			rotate(u);
		}
	}
	inline int access(int u,int k){
		int v;
		for(v=0;u;v=u,u=fa[u]){
			splay(u);
		//	cerr<<v<<" "<<fa[u]<<" "<<u<<" "<<c[u]<<" "<<val[u]<<'\n';
			if(c[u]+val[u]>k)break;
			c[rc(u)]=c[u],rc(u)=v;
		}
		if(v)c[v]=k-val[u];
		return val[u];
	}
}
int m,fa[N],dep[N],ans[N];
struct ask{
	int u,t,id;
	friend inline bool operator <(cs ask &a,cs ask &b){
		return a.t==b.t?a.u<b.u:a.t<b.t;
	}
}p[N];
int main(){
	n=read()+1,m=read();
	for(int i=2;i<=n;i++)fa[i]=read()+1,dep[i]=dep[fa[i]]+1;
	for(int i=1;i<=n;i++)Lct::init(i,fa[i],2*dep[i]);
	for(int i=1;i<=m;i++){
		int u=read()+1,t=read();
		p[i].u=u,p[i].t=t+dep[u],p[i].id=i;
	}
	sort(p+1,p+m+1);
	for(int i=1;i<=m;i++)
	ans[p[i].id]=dep[p[i].u]-Lct::access(p[i].u,p[i].t)+p[i].t;
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<" ";
	}
}
//orzlxr!


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
const int P=31;
int dp[N][N];
int cp[N];
int a,b;
ll gh[N];
unordered_map <ll,int> ma;
ll powe(ll a,ll b)
{
    ll res=1;
    while(b>0)
    {
        if(b%2)
            res=(res*a)%mod;
        b=b/2;
        a=(a*a)%mod;
    }
    return res;
}
void fun(int n)
{
    cp[0]=a;
    int id,i,j,k,l;
    for(id=1;id<n;id++)
    {
        int ans=cp[id-1]+a;
        for(i=id-1;i>=0;i--)
        {
            if(dp[i+1][id]==1){
                ans=min(ans,cp[i]+b);
            }
        }
        cp[id]=ans;
    }
    return ;
}
ll gun(string str)
{
    int i,j,l;
    l=str.size();
    ll ans=0;
    for(i=0;i<l;i++)
    {
        ll xd=((str[i]-96)*gh[i])%mod;
        ans=(ans+xd)%mod;
    }
    return ans;
}
int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll inv=powe(P,1000000005);
    int n,i,j,k,l,q,m;
    gh[0]=1;
    for(i=1;i<N;i++)
    {
        gh[i]=(gh[i-1]*P)%mod;
    }

    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        ll hash=gun(sd);
        ma[hash]++;
        for(j=0;j<i;j++)
        {
            ll pk=str[j]-96;
            hash=(hash-pk+mod)%mod;
            hash=(hash*inv)%mod;
            ma[hash]++;
        }
        if(i==(n-1))   continue;

        ll citu=0;
        for(j=i+1;j<n;j++)
        {
            ll hu=((str[j]-96)*gh[j-i-1])%mod;
            citu=(citu+hu)%mod;
            if(ma[citu]==0)  continue;
            else {
                dp[i+1][j]=1;
            }
        }
    }
    ma.clear();
    fun(n);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
const int P=31;
int dp[N][N];
int cp[N];
int a,b;
ll gh[N];
unordered_map <ll,int> ma;
ll powe(ll a,ll b)
{
    ll res=1;
    while(b>0)
    {
        if(b%2)
            res=(res*a)%mod;
        b=b/2;
        a=(a*a)%mod;
    }
    return res;
}
void fun(int n)
{
    cp[0]=a;
    int id,i,j,k,l;
    for(id=1;id<n;id++)
    {
        int ans=cp[id-1]+a;
        for(i=id-1;i>=0;i--)
        {
            if(dp[i+1][id]==1){
                ans=min(ans,cp[i]+b);
            }
        }
        cp[id]=ans;
    }
    return ;
}
ll gun(string str)
{
    int i,j,l;
    l=str.size();
    ll ans=0;
    for(i=0;i<l;i++)
    {
        ll xd=((str[i]-96)*gh[i])%mod;
        ans=(ans+xd)%mod;
    }
    return ans;
}
int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll inv=powe(P,1000000005);
    int n,i,j,k,l,q,m;
    gh[0]=1;
    for(i=1;i<N;i++)
    {
        gh[i]=(gh[i-1]*P)%mod;
    }

    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        ll bitu=gun(sd);
        ma[bitu]++;
        for(j=0;j<i;j++)
        {
            //sd.erase(sd.begin());
            ll pk=str[j]-96;
            bitu=(bitu-pk+mod)%mod;
            bitu=(bitu*inv)%mod;
            ma[bitu]++;
        }
        if(i==(n-1))   continue;
        //string pk="";
        ll citu=0;
        for(j=i+1;j<n;j++)
        {
            //pk.pb(str[j]);
            ll hu=((str[j]-96)*gh[j-i-1])%mod;
            citu=(citu+hu)%mod;
            if(ma[citu]==0)  continue;
            else {
                dp[i+1][j]=1;
            }
        }
    }
    ma.clear();
    fun(n);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
int dp[N][N];
int cp[N];
int a,b;
unordered_map < string,int> ma;
void fun(int n)
{
    cp[0]=a;
    int i,j,k,l;
    for(id=1;id<n;id++)
    {
        int ans=cp[id-1]+a;
        for(i=id-1;i>=0;i--)
        {
            if(dp[i+1][id]==1){
                ans=min(ans,cp[i]+b);
            }
        }
        cp[id]=ans;
    }
    return ;
}
int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n,i,j,k,l,q,m;
    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        ma[sd]++;
        for(j=0;j<i;j++)
        {
            sd.erase(sd.begin());
            ma[sd]++;
        }
        if(i==(n-1))   continue;
        string pk="";
        for(j=i+1;j<n;j++)
        {
            pk.pb(str[j]);
            if(ma[pk]==0)  continue;
            else {
                dp[i+1][j]=1;
            }
        }
    }
    ma.clear();
    fun(n);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
int dp[N][N];
int cp[N];
int a,b;
unordered_map < string,int> ma;
void fun(int id)
{
    if(cp[id]!=-1)  return ;
    if(id==0){
        cp[id]=a;
        return ;
    }
    int i,j,k,l;
    fun(id-1);
    int ans=cp[id-1]+a;
    for(i=id-1;i>=0;i--)
    {
        if(dp[i+1][id]==1){
            fun(i);
            ans=min(ans,cp[i]+b);
        }
    }
    cp[id]=ans;
    return ;
}
int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n,i,j,k,l,q,m;
    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        ma[sd]++;
        for(j=0;j<i;j++)
        {
            sd.erase(sd.begin());
            ma[sd]++;
        }
        if(i==(n-1))   continue;
        string pk="";
        for(j=i+1;j<n;j++)
        {
            pk.pb(str[j]);
            if(ma[pk]==0)  continue;
            else {
                dp[i+1][j]=1;
            }
        }

    }

    fun(n-1);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
int dp[N][N];
int cp[N];
int a,b;
unordered_map < string,int> ma;
void fun(int id)
{
    if(cp[id]!=-1)  return ;
    if(id==0){
        cp[id]=a;
        return ;
    }
    int i,j,k,l;
    fun(id-1);
    int ans=cp[id-1]+a;
    for(i=id-1;i>=0;i--)
    {
        if(dp[i+1][id]==1){
            fun(i);
            ans=min(ans,cp[i]+b);
        }
    }
    cp[id]=ans;
    return ;
}
int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n,i,j,k,l,q,m;
    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        ma[sd]++;
        for(j=0;j<i;j++)
        {
            sd.erase(sd.begin());
            ma[sd]++;
        }
        if(i==(n-1))   continue;
        string pk="";
        for(j=i+1;j<n;j++)
        {
            pk.pb(str[j]);
            if(ma[pk]==0)  continue;
            else {
                dp[i+1][j]=1;
            }
        }
    }
    ma.clear();
    fun(n-1);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mod 1000000007
#define pb push_back
#define mp make_pair
#define PI 3.14159265
#define pf push_front
#define ll long long int
typedef pair<int,int>  pii;
uint64_t seed = reinterpret_cast<uint64_t>(new char);
mt19937 rd(seed);
//uniform_int_distribution<int> rg(1, n);
//int RandomNumber = rg(rd);
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;

const int N=5008;
const int P=31;
int dp[N][N];
int cp[N];
int a,b;
ll gh[N];
unordered_map <ll,int> ma;
ll powe(ll a,ll b)
{
    ll res=1;
    while(b>0)
    {
        if(b%2)
            res=(res*a)%mod;
        b=b/2;
        a=(a*a)%mod;
    }
    return res;
}
int lps[N];
void computeLPSArray(string pat, int M)
{
    int len = 0;
   // M = length of string pattern
    // size of lps is = M
    lps[0] = 0;
    int i = 1;
    while (i < M)
    {
        if (pat[i] == pat[len])
        {
            len++;
            lps[i] = len;
            i++;
        }
        else
        {
            if (len != 0)
            {
                len = lps[len-1];
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }
    return;
}
int  KMPSearch(string txt,string pat)
{
    int M = pat.size();
    int N = txt.size();
    if(M>N)  return 0;
 // time complexity = O(M+N) //
    computeLPSArray(pat, M);

    int i = 0;  // index for txt[]
    int j  = 0;  // index for pat[]
    while (i < N)
    {
        if (pat[j] == txt[i])
        {
            j++;
            i++;
        }
        if (j == M)
        {
            //printf("Found pattern at index %d \n", i-j);
            return 1;
            j = lps[j-1];
        }
        else if (i < N && pat[j] != txt[i])
        {
            if (j != 0)
                j = lps[j-1];
            else
                i = i+1;
        }
    }
    return 0;
}
void fun(int n)
{
    cp[0]=a;
    int id,i,j,k,l;
    for(id=1;id<n;id++)
    {
        int ans=cp[id-1]+a;
        for(i=id-1;i>=0;i--)
        {
            if(dp[i+1][id]==1){
                ans=min(ans,cp[i]+b);
            }
        }
        cp[id]=ans;
    }
    return ;
}

int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll inv=powe(P,1000000005);
    int n,i,j,k,l,q,m;
    gh[0]=1;
    for(i=1;i<N;i++)
    {
        gh[i]=(gh[i-1]*P)%mod;
    }

    string str;
    memset(cp,-1,sizeof(cp));
    cin>>n>>a>>b;
    cin>>str;
    for(i=0;i<str.size();i++)
    {
        string sd=str.substr(0,i+1);
        if(i==(n-1))  continue;
        l=i+1;
        int r=n-1;
        while((r-l)>1)
        {
            int mid=(l+r)/2;
            int len=(mid-i);
            if(KMPSearch(sd,str.substr(i+1,len))==1){
                l=mid;
            }
            else
                r=mid;
        }
        int limit=i-1;
        if(KMPSearch(sd,str.substr(i+1,r-i))==1){
            limit=r;
        }
        else if(KMPSearch(sd,str.substr(i+1,l-i))==1){
            limit=l;
        }
        for(j=i+1;j<=limit;j++)
        {
            dp[i+1][j]=1;
        }
    }
    ma.clear();
    fun(n);
    cout<<cp[n-1]<<endl;
    return 0;
}


#include <iostream>
#include <string>

#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <list>

#include <algorithm>
#include <utility>
#include <functional>
#include <numeric>

#include <iomanip>
#include <cmath>

typedef long long int64;
#define all(x) (x).begin(), (x).end()

using namespace std;

struct Node
{
	vector<int64> to;
	int64 c;

	Node()
	{
		c = -1;
	}
};

int64 MOD = 1e9 + 7;
double PI = acos(-1);

int64 n, a, b;
vector<Node> g;

void Z(int64 u, string &str)
{
	static vector<int64> z(str.size());
	int64 l = u, r = u;

	for (int64 i = u + 1; i < str.size(); i++){

		z[i] = 0;
		if (i >= l && i < r){
			z[i] = min(z[u + i - l], r - i);
		}

		while (i + z[i] < n && str[i+z[i]] == str[u + z[i]]){
			z[i]++;
		}

		if (i + z[i] > r){
			l = i;
			r = i + z[i];
		}

		int64 d = z[i];
		if (u + z[i]>i)
			d = i - u;
		g[i].to.push_back(i+d);

	}
}

int64 dfs(int64 u)
{
	if (g[u].c != -1){
		return g[u].c;
	}

	if (u==n){
		return 0;
	}

	g[u].c = dfs(u + 1) + a;

	for (int64 i = 0; i < g[u].to.size(); i++){
		int64 to = g[u].to[i];

		g[u].c = min(g[u].c, dfs(to) + b);
	}

	return g[u].c;
}

int main()
{
#ifdef _DEBUG
	freopen("ReadMe.txt", "r", stdin);
#endif

	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> n >> a >> b;

	string str;
	cin >> str;

	g.resize(n+1);

	for (int64 i = 0; i < n; i++)
	{
		Z(i, str);
	}

	cout << dfs(0);

	return 0;
}


#include <iostream>
#include <string>

#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <list>

#include <algorithm>
#include <utility>
#include <functional>
#include <numeric>

#include <iomanip>
#include <cmath>

typedef long long int64;
#define all(x) (x).begin(), (x).end()

using namespace std;

struct Node
{
	vector<int64> to;
	int64 c;

	Node()
	{
		c = -1;
	}
};

int64 MOD = 1e9 + 7;
double PI = acos(-1);

int64 n, a, b;
vector<Node> g;

void Z(int64 u, string &str)
{
	vector<int64> z(str.size());
	int64 l = u, r = u;

	for (int64 i = u + 1; i < str.size(); i++){

		if (i >= l && i < r){
			z[i] = min(z[u + i - l], r - i);
		}

		while (i + z[i] < n && u+z[i]<i && str[i+z[i]] == str[u + z[i]]){
			z[i]++;
		}

		if (i + z[i] > r){
			l = i;
			r = i + z[i];
		}

		g[i].to.push_back(i + z[i]);

	}
}

int64 dfs(int64 u)
{
	if (g[u].c != -1){
		return g[u].c;
	}

	if (u==n){
		return 0;
	}

	g[u].c = dfs(u + 1) + a;

	for (int64 i = 0; i < g[u].to.size(); i++){
		int64 to = g[u].to[i];

		g[u].c = min(g[u].c, dfs(to) + b);
	}

	return g[u].c;
}

int main()
{
#ifdef _DEBUG
	freopen("ReadMe.txt", "r", stdin);
#endif

	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> n >> a >> b;

	string str;
	cin >> str;

	g.resize(n+1);

	for (int64 i = 0; i < n; i++)
	{
		Z(i, str);
	}

	cout << dfs(0);

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("unroll-loops")
#include <climits>
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_set>
#include <string>
#include <map>
#include <unordered_map>
#include <random>
#include <set>
#include <cassert>
#include <functional>
#include <iomanip>
#include <queue>
#include <numeric>
#include <bitset>
#include <iterator>

using namespace std;

const int N = 5050;

mt19937 gen(time(NULL));
#define forn(i, n) for (int i = 0; i < n; i++)
#define ford(i, n) for (int i = n - 1; i >= 0; i--)
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#define all(a) (a).begin(), (a).end()
#define pii pair<int, int>
#define mp make_pair
#define endl '\n'
#define vi vector<int>

typedef long long ll;

template<typename T = int>
inline T read() {
	T val = 0, sign = 1; char ch;
	for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar())
		if (ch == '-') sign = -1;
	for (; ch >= '0' && ch <= '9'; ch = getchar())
		val = val * 10 + ch - '0';
	return sign * val;
}

int dp[N];

vector<int> zf(string s) {
	int n = s.size();
	vector<int> zf(n);
	zf[0] = n;
	for (int i = 1, l = 0, r = 1; i < n; i++) {
		if (i < r)
			zf[i] = min(r - i, zf[i - l]);
		while (i + zf[i] < n && s[zf[i]] == s[i + zf[i]]) zf[i]++;
		if (i + zf[i] > r) {
			l = i, r = i + zf[i];
		}
	}
	return zf;
}

int pos[N][N];
vector<pii> info[N];

void solve() {
	int n = read(), a = read(), b = read();
	string s; cin >> s;
	dp[0] = a;

	for (int i = 0; i < n; i++) {
		auto p = zf(s.substr(i, n - i));
		for (int j = i; j < n; j++) {
			info[j].push_back(mp(p[j - i], i));
		}
	}

	fill_n(&pos[0][0], N * N, 1e9);

	for (int i = 0; i < n; i++) {
		sort(all(info[i]), greater<pii>());
		auto& v = info[i];
		int minpos = v[0].second, len = v[0].first;
		int j = 0;
		for (; len; len--) {
			while (j < v.size() && v[j].first == len) {
				minpos = min(minpos, v[j].second);
				j++;
			};
			pos[len][i] = minpos;
		}
	}

	for (int i = 1; i < n; i++) {
		dp[i] = dp[i - 1] + a;
		for (int len = 1; len <= i; len++) {
			int p = pos[len][i - len + 1];
			if (p + len - 1 < i - len + 1)
				dp[i] = min(dp[i], dp[i - len] + b);
		}
	}

	cout << dp[n - 1] << endl;
}

signed main() {
	int t = 1;

	ios_base::sync_with_stdio(0);
	cin.tie(0);

	while (t--) {
		clock_t z = clock();
		solve();
		debug("Total Time: %.3f\n", (double)(clock() - z) / CLOCKS_PER_SEC);
	}
}


import sys
sys.setrecursionlimit(10**8)
n,a,b=[int(i) for i in raw_input().split()]
s=raw_input()
def fun(ind=0):
    if (ind>=n):return 0
    if (DP[ind]!=-1):return DP[ind]
    DP[ind]=a+fun(ind+1)

    #bsearch

    lo=ind;hi=n;best=-1;
    while(lo<hi):
        mid=(lo+hi)//2
        if (s[ind:mid+1] in s[0:ind]):
            best=mid
            lo=mid+1
        else:
            hi=mid
##    for i in range(ind,n):
##        if (s[ind:i+1] in s[0:ind]):
##            DP[ind]=min(DP[ind],fun(i+1)+b)
##        else: break
    if (best!=-1):DP[ind]=min(DP[ind],b+fun(best+1))
    return DP[ind]
DP=[-1 for i in range(n+5)]
print(fun())


use std::io::{self, prelude::*, BufWriter};

fn solve<R: BufRead, W: Write>(mut input: FastInput<R>, mut w: W) {
    let n: usize = input.token();
    let a: u64 = input.token();
    let b: u64 = input.token();
    let s: Vec<u8> = input.token();

    let mut first: Vec<Vec<_>> = (0..n).map(|i| vec![i; n - i]).collect();
    for i in 0..n {
        let x = z(&s[i..]);
        for j in i + 1..n {
            if x[j - i] > 0 && first[j][x[j - i] - 1] > i {
                first[j][x[j - i] - 1] = i;
            }
        }
    }
    for v in first.iter_mut() {
        for i in (0..v.len() - 1).rev() {
            v[i] = std::cmp::min(v[i], v[i + 1]);
        }
    }
    let mut dp = vec![0u64; n];
    dp[0] = a;
    for i in 1..n {
        dp[i] = dp[i - 1] + a;
        for j in 1..=i {
            let len = i + 1 - j;
            if first[j][len - 1] + len <= j {
                dp[i] = std::cmp::min(dp[i], b + dp[j - 1]);
            }
        }
    }
    write!(w, "{}\n", dp[n - 1]);
}

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let input = FastInput::from(stdin.lock());
    let writer = BufWriter::new(stdout.lock());
    solve(input, writer);
}

pub fn z(s: &[u8]) -> Vec<usize> {
    let mut ret = vec![0; s.len()];
    let mut l = 0;
    let mut r = 0;
    for i in 1..s.len() {
        if i <= r {
            ret[i] = std::cmp::min(r + 1 - i, ret[i - l]);
        }
        while i + ret[i] < s.len() && s[ret[i]] == s[ret[i] + i] {
            ret[i] += 1;
        }
        if i + ret[i] > r + 1 {
            l = i;
            r = i + ret[i] - 1;
        }
    }
    ret
}

trait TokenStream<T> {
    fn token(&mut self) -> T;
}

struct FastInput<R> {
    stdin: R,
    pos: usize,
}

impl<R: BufRead> From<R> for FastInput<R> {
    fn from(r: R) -> Self {
        FastInput { stdin: r, pos: 0 }
    }
}

impl<R: BufRead> TokenStream<u8> for FastInput<R> {
    fn token(&mut self) -> u8 {
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                while self.pos < buf.len() {
                    self.pos += 1;
                    if buf[self.pos - 1] > 32 {
                        return buf[self.pos - 1];
                    }
                }
                if self.pos == 0 {
                    return 0;
                }
            } else {
                return 0;
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

impl<R: BufRead> TokenStream<Vec<u8>> for FastInput<R> {
    fn token(&mut self) -> Vec<u8> {
        let mut ans = Vec::new();
        let mut parse_token = false;
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                if !parse_token {
                    while self.pos < buf.len() && buf[self.pos] <= 32 {
                        self.pos += 1;
                    }
                }
                while self.pos < buf.len() && buf[self.pos] > 32 {
                    parse_token = true;
                    ans.push(buf[self.pos]);
                    self.pos += 1;
                }
                if self.pos != buf.len() || self.pos == 0 {
                    return ans;
                }
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

macro_rules! impl_token_stream {
    ($($t:ident),+) => {$(
        impl<R: BufRead> TokenStream<$t> for FastInput<R> {
           fn token(&mut self) -> $t {
                let mut ans = 0;
                let mut parse_token = false;
                loop {
                    if let Ok(buf) = self.stdin.fill_buf() {
                        if !parse_token {
                            while self.pos < buf.len() && buf[self.pos] <= 32 {
                                self.pos += 1;
                            }
                        }
                        while self.pos < buf.len() && buf[self.pos] > 32 {
                            parse_token = true;
                            ans = ans * 10 + (buf[self.pos] - b'0') as $t;
                            self.pos += 1;
                        }
                        if self.pos != buf.len() || self.pos == 0 {
                            return ans;
                        }
                    }
                    self.stdin.consume(self.pos);
                    self.pos = 0;
                }
           }
        }
    )+}
}

impl_token_stream!(usize, u64);


use std::io::{self, prelude::*, BufWriter};

fn solve<R: BufRead, W: Write>(mut input: FastInput<R>, mut w: W) {
    let n: usize = input.token();
    let a: u64 = input.token();
    let b: u64 = input.token();
    let s: Vec<u8> = input.token();

    let mut first: Vec<Vec<_>> = (0..n).map(|i| vec![i; n - i]).collect();
    for (i, x) in (0..n).map(|i| z(&s[i..])).enumerate() {
        for (j, len) in x.iter().enumerate().skip(1).filter(|(_, &len)| len > 0) {
            first[i + j][len - 1] = std::cmp::min(first[i + j][len - 1], i);
        }
    }
    for v in first.iter_mut() {
        for i in (0..v.len() - 1).rev() {
            v[i] = std::cmp::min(v[i], v[i + 1]);
        }
    }
    let mut dp = vec![0u64; n];
    dp[0] = a;
    for i in 1..n {
        dp[i] = dp[i - 1] + a;
        for j in 1..=i {
            let len = i + 1 - j;
            if first[j][len - 1] + len <= j {
                dp[i] = std::cmp::min(dp[i], b + dp[j - 1]);
            }
        }
    }
    write!(w, "{}\n", dp[n - 1]);
}

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let input = FastInput::from(stdin.lock());
    let writer = BufWriter::new(stdout.lock());
    solve(input, writer);
}

pub fn z(s: &[u8]) -> Vec<usize> {
    let mut ret = vec![0; s.len()];
    let mut l = 0;
    let mut r = 0;
    for i in 1..s.len() {
        if i <= r {
            ret[i] = std::cmp::min(r + 1 - i, ret[i - l]);
        }
        while i + ret[i] < s.len() && s[ret[i]] == s[ret[i] + i] {
            ret[i] += 1;
        }
        if i + ret[i] > r + 1 {
            l = i;
            r = i + ret[i] - 1;
        }
    }
    ret
}

trait TokenStream<T> {
    fn token(&mut self) -> T;
}

struct FastInput<R> {
    stdin: R,
    pos: usize,
}

impl<R: BufRead> From<R> for FastInput<R> {
    fn from(r: R) -> Self {
        FastInput { stdin: r, pos: 0 }
    }
}

impl<R: BufRead> TokenStream<u8> for FastInput<R> {
    fn token(&mut self) -> u8 {
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                while self.pos < buf.len() {
                    self.pos += 1;
                    if buf[self.pos - 1] > 32 {
                        return buf[self.pos - 1];
                    }
                }
                if self.pos == 0 {
                    return 0;
                }
            } else {
                return 0;
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

impl<R: BufRead> TokenStream<Vec<u8>> for FastInput<R> {
    fn token(&mut self) -> Vec<u8> {
        let mut ans = Vec::new();
        let mut parse_token = false;
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                if !parse_token {
                    while self.pos < buf.len() && buf[self.pos] <= 32 {
                        self.pos += 1;
                    }
                }
                while self.pos < buf.len() && buf[self.pos] > 32 {
                    parse_token = true;
                    ans.push(buf[self.pos]);
                    self.pos += 1;
                }
                if self.pos != buf.len() || self.pos == 0 {
                    return ans;
                }
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

macro_rules! impl_token_stream {
    ($($t:ident),+) => {$(
        impl<R: BufRead> TokenStream<$t> for FastInput<R> {
           fn token(&mut self) -> $t {
                let mut ans = 0;
                let mut parse_token = false;
                loop {
                    if let Ok(buf) = self.stdin.fill_buf() {
                        if !parse_token {
                            while self.pos < buf.len() && buf[self.pos] <= 32 {
                                self.pos += 1;
                            }
                        }
                        while self.pos < buf.len() && buf[self.pos] > 32 {
                            parse_token = true;
                            ans = ans * 10 + (buf[self.pos] - b'0') as $t;
                            self.pos += 1;
                        }
                        if self.pos != buf.len() || self.pos == 0 {
                            return ans;
                        }
                    }
                    self.stdin.consume(self.pos);
                    self.pos = 0;
                }
           }
        }
    )+}
}

impl_token_stream!(usize, u64);


import java.util.ArrayList;
import java.util.Scanner;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Andy Phan
 */
public class p001121f {
    static String arr;
    static int[] dp;
    static boolean[] done;
    static int a, b;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        a = in.nextInt();
        b = in.nextInt();
        dp = new int[n];
        done = new boolean[n];
        arr = in.next();
        System.out.println(dp(n-1));
    }

    static int dp(int pos) {
        if(pos < 0) return 0;
        if(pos == 0) return dp[pos] = a;
        if(done[pos]) return dp[pos];
        done[pos] = true;
        int min = a+dp(pos-1);
        int lo = -1;
        int hi = pos;
        for(int i = 0; i < 13; i++) {
            int mid = (lo+hi)/2;
            if(search(arr.substring(0, pos-mid).toCharArray(),
                arr.substring(pos-mid, pos+1).toCharArray(), KMP_Construct(arr.substring(pos-mid, pos+1).toCharArray()))) {
                lo = mid;
            } else {
                hi = mid;
            }
        }
        if(lo == -1) return dp[pos] = min;
        min = Math.min(min, dp(pos-lo-1)+b);
        return dp[pos] = min;
    }

    // Given a pattern string w, return the prefix array. //%
    // p[i] indicates the length of the longest prefix //%
    // that is also a substring ending at i.  O(|w|) //%
    static int[] KMP_Construct(char[] w) {
            int n = w.length + 1, k = 0;  int[] p = new int[n];
            p[0] = 0;
            for(int i = 2; i < n; ++i) {
                    while(k > 0 && w[k] != w[i-1]) k = p[k];
                    if(w[k] == w[i-1]) k++;
                    p[i] = k;
            }
            return p;
    }

    // Given the prefix array of a pattern, search the //%
    // text for all occurrences of the pattern.  O(|s|) //%
    static boolean search(char[] s, char[] w, int[] p) {
            int k = 0;
            for(int i = 0; i < s.length; ++i) {
                    while(k > 0 && w[k] != s[i]) k = p[k];
                    if(w[k] ==
                        s[i]) k++;
                    if(k == w.length) { return true; }
            }
            return false;
    }
}


import java.io.*;
import java.util.*;

public class D {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);
        Solver solver = new Solver();
        solver.solve(in, out);
        out.close();
    }

    private static class Solver {

        private int min(int a, int b) {
            return a > b ? b : a;
        }

        private void solve(InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int a = in.nextInt();
            int b = in.nextInt();
            char[] s = in.next().toCharArray();

            int[] dp = new int[n];
            dp[0] = a;
            for (int i = 1; i < n; i++) {
                int m = i + 1;
                int[] z = new int[m];
                for (int j = 1, l = 0, r = 0; j < m; j++) {
                    if (j <= r) {
                        z[j] = min(z[j - l], r - j + 1);
                    }
                    while (j + z[j] < m && s[m - z[j] - 1] == s[m - j - z[j] - 1]) {
                        z[j]++;
                    }
                    if (j + z[j] - 1 > r) {
                        l = j;
                        r = j + z[j] - 1;
                    }
                }

                dp[i] = dp[i - 1] + a;
                for (int j = 0; j < m; j++) {
                    if (z[j] > 0) {
                        dp[i] = min(dp[i], dp[i - min(z[j], j)] + b);
                    }
                }
            }

            out.println(dp[n - 1]);
        }
    }

    private static class InputReader {
        private BufferedReader br;
        private StringTokenizer st;

        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
        }

        private int nextInt() {
            return Integer.parseInt(next());
        }

        private long nextLong() {
            return Long.parseLong(next());
        }

        private double nextDouble() {
            return Double.parseDouble(next());
        }

        private String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }

        private String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
    }
}


import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/*
Прокрастинирую
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int INF = (int) (1e9 + 10);
    static final int MOD = (int) (1e9 + 7);
    static final int N = (int) (5e3 + 10);
    static final int LOGN = 20;

    static int[] zFunction(char[] s) {
        int n = s.length;
        int[] z = new int[n];
        for (int i = 1, l = 0, r = 0; i < n; i++) {
            if (i <= r) {
                z[i] = Math.min(z[i - l], r - i + 1);
            }
            while (i + z[i] < n && s[i + z[i]] == s[z[i]]) {
                z[i]++;
            }
            if (i + z[i] - 1 > r) {
                l = i;
                r = i + z[i] - 1;
            }
        }
        return z;
    }

    static void solve() {
        int n = in.nextInt();
        int a = in.nextInt();
        int b = in.nextInt();
        char[] s = in.next().toCharArray();

        int[] dp = new int[n];
        dp[0] = a;
        for (int i = 1; i < n; i++) {
            dp[i] = dp[i - 1] + a;

            char[] ss = new char[i + 1];
            for (int j = 0; j < i + 1; j++) {
                ss[j] = s[i - j];
            }
            int[] z = zFunction(ss);

            for (int j = 0; j < i + 1; j++) {
                if (z[j] <= j) {
                    dp[i] = Math.min(dp[i], dp[i - z[j]] + b);
                }
            }
        }

        out.println(dp[n - 1]);
    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("input.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int q = 1;
//        q = in.nextInt();

        while (q-- > 0) {
            solve();
        }

        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }
}


import java.io.*;
import java.util.*;
public class B{
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.flush();out.close();
    }
        static class TaskE {
            final int max=5010;
            final int maxc=Integer.MAX_VALUE/100;
            int n,a,b;
            char ch[];
            int dp[]=new int[max];
            int find(int p){
                char str[]=new char[n+1];
                int st=-1;
                for(int i=p;i<n;i++)str[++st]=ch[i];
                str[++st]='$';
                for(int i=0;i<p;i++)str[++st]=ch[i];

                    int L = 0, R = 0;
                    int Z[]=new int[n+1];
                    int ans=0;
                    for(int i = 1; i <= st; ++i) {
                        if(i > R){

                            L = R = i;

                            while(R <= st && str[R - L] == str[R])
                                R++;

                            Z[i] = R - L;
                            R--;

                        }
                        else{
                            int k = i - L;
                            if(Z[k] < R - i + 1)
                                Z[i] = Z[k];
                            else{
                                L = i;
                              while(R <= st && str[R - L] == str[R])
                                R++;

                                Z[i] = R - L;
                                R--;
                            }
                        }
                        if(i>n-p)ans=Math.max(ans,Z[i]);
                        // System.out.println(Z[i]+" "+p);
                    }

                    return ans;
                }

           public void solve(int testNumber, InputReader in, PrintWriter out) {
            n=in.nextInt();a=in.nextInt();b=in.nextInt();
            ch=in.next().trim().toCharArray();
            dp[0]=a;
            for(int i=1;i<n;i++)dp[i]=maxc;
            for(int i=1;i<n;i++){
                dp[i]=Math.min(dp[i],dp[i-1]+a);
                int maxl=find(i);
                for(int j=i;j-i<maxl;j++)dp[j]=Math.min(dp[j],dp[i-1]+b);
            }
            out.println(dp[n-1]);
          }
//         pair ja[][];long w[];int from[],to[],c[];
//             void make(int n,int m,InputReader in){
//              ja=new pair[n+1][];w=new long[m];from=new int[m];to=new int[m];c=new int[n+1];
//              for(int i=0;i<m;i++){
//               int u=in.nextInt(),v=in.nextInt();long wt=in.nextLong();
//               c[u]++;c[v]++;from[i]=u;to[i]=v;w[i]=wt;
//              }
//              for(int i=1;i<=n;i++){
//               ja[i]=new pair[c[i]];c[i]=0;
//              }
//              for(int i=0;i<m;i++){
//               ja[from[i]][c[from[i]]++]=new pair(to[i],w[i]);
//               ja[to[i]][c[to[i]]++]=new pair(from[i],w[i]);
//              }
//             }
//        int[] radixSort(int[] f){ return radixSort(f, f.length); }
//    int[] radixSort(int[] f, int n)
//    {
//        int[] to = new int[n];
//        {
//            int[] b = new int[65537];
//            for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
//            for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
//            for(int i = 0;i < n;i++)to[b[f[i]&0xffff]++] = f[i];
//            int[] d = f; f = to;to = d;
//        }
//        {
//            int[] b = new int[65537];
//            for(int i = 0;i < n;i++)b[1+(f[i]>>>16)]++;
//            for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
//            for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
//            int[] d = f; f = to;to = d;
//        }
//        return f;
//    }
    }
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
            st = null;
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Solution {
    static final int INF = (int) 1e9;
    static final int mod = (int) (1e9 + 7);
    static final int UNCALC = -1;
    static int n, a, b;
    static int longest[];
    static int memo[];

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = sc.nextInt();
        a = sc.nextInt();
        b = sc.nextInt();
        longest = new int[n];
        char[] s = sc.next().toCharArray();
        for (int i = 0; i < n; i++) {
            char[] tmp = new char[n - i];
            int c = 0;
            for (int j = i; j < n; j++)
                tmp[c++] = s[j];
            int[] z = zAlgo(tmp);
            int idx = i + 1;
            for (int j = 1; idx < n; j++, idx++) {
                longest[idx] = Math.max(Math.min(z[j], j), longest[idx]);
            }
        }
        memo = new int[n];
        Arrays.fill(memo, UNCALC);
        out.println(dp(0));
        out.flush();
        out.close();
    }

    static int dp(int i) {
        if (i >= n) return 0;
        if (memo[i] != UNCALC) return memo[i];
        int min = a + dp(i + 1);
        for (int j = 1; j <= longest[i]; j++)
            min = Math.min(min, b + dp(i + j));
        return memo[i] = min;
    }

    static int[] zAlgo(char[] s) {
        int n = s.length;
        int[] z = new int[n];
        for (int i = 1, l = 0, r = 0; i < n; ++i) {
            if (i <= r)
                z[i] = Math.min(r - i + 1, z[i - l]);
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
                ++z[i];
            if (i + z[i] - 1 > r)
                r = i + z[l = i] - 1;
        }
        return z;
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

        public Scanner(String file) throws Exception {
            br = new BufferedReader(new FileReader(file));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

        public Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }

        public void waitForInput() throws InterruptedException {
            Thread.sleep(3000);
        }

        public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

    }
}


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Solution {
    static final int INF = (int) 1e9;
    static final int mod = (int) (1e9 + 7);
    static final int UNCALC = -1;
    static int n, a, b;
    static int longest[];
    static int memo[];

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = sc.nextInt();
        a = sc.nextInt();
        b = sc.nextInt();
        longest = new int[n];
        char[] s = sc.next().toCharArray();
        for (int i = 0; i < n; i++) {
            char[] tmp = new char[n - i];
            int c = 0;
            for (int j = i; j < n; j++)
                tmp[c++] = s[j];
            int[] z = zAlgo(tmp);
            for (int j = 0; j < z.length; j++) {
                int min = j + i;
                longest[j + i] = Math.max(Math.min(z[j], min), longest[j + i]);
            }
        }
        memo = new int[n];
        Arrays.fill(memo, UNCALC);
        out.println(dp(0));
        out.flush();
        out.close();
    }

    static int dp(int i) {
        if (i >= n) return 0;
        if (memo[i] != UNCALC) return memo[i];
        int min = a + dp(i + 1);
        for (int j = 1; j <= longest[i]; j++) {
            int nxt = i + j + 1;
            min = Math.min(min, b + dp(nxt));
        }
        return memo[i] = min;
    }

    static int[] zAlgo(char[] s) {
        int n = s.length;
        int[] z = new int[n];
        for (int i = 1, l = 0, r = 0; i < n; ++i) {
            if (i <= r)
                z[i] = Math.min(r - i + 1, z[i - l]);
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
                ++z[i];
            if (i + z[i] - 1 > r)
                r = i + z[l = i] - 1;
        }
        return z;
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

        public Scanner(String file) throws Exception {
            br = new BufferedReader(new FileReader(file));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

        public Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }

        public void waitForInput() throws InterruptedException {
            Thread.sleep(3000);
        }

        public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

    }
}


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Solution {
    static final int INF = (int) 1e9;
    static final int mod = (int) (1e9 + 7);
    static final int UNCALC = -1;
    static int n, a, b;
    static int longest[];
    static int memo[];

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = sc.nextInt();
        a = sc.nextInt();
        b = sc.nextInt();
        longest = new int[n];
        char[] s = sc.next().toCharArray();
        for (int i = 0; i < n; i++) {
            char[] tmp = new char[n - i];
            int c = 0;
            for (int j = i; j < n; j++)
                tmp[c++] = s[j];
            int[] z = zAlgo(tmp);
            int idx = i + 1;
            for (int j = 1; j < z.length; j++, idx++) {
                longest[idx] = Math.max(Math.min(z[j], idx), longest[idx]);
            }
        }
        memo = new int[n];
        Arrays.fill(memo, UNCALC);
        out.println(dp(0));
        out.flush();
        out.close();
    }

    static int dp(int i) {
        if (i >= n) return 0;
        if (memo[i] != UNCALC) return memo[i];
        int min = a + dp(i + 1);
        for (int j = 1; j <= longest[i]; j++) {
            int nxt = i + j;
            min = Math.min(min, b + dp(nxt));
        }
        return memo[i] = min;
    }

    static int[] zAlgo(char[] s) {
        int n = s.length;
        int[] z = new int[n];
        for (int i = 1, l = 0, r = 0; i < n; ++i) {
            if (i <= r)
                z[i] = Math.min(r - i + 1, z[i - l]);
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
                ++z[i];
            if (i + z[i] - 1 > r)
                r = i + z[l = i] - 1;
        }
        return z;
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

        public Scanner(String file) throws Exception {
            br = new BufferedReader(new FileReader(file));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

        public Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }

        public void waitForInput() throws InterruptedException {
            Thread.sleep(3000);
        }

        public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

    }
}