You are given a graph with n nodes and m directed edges. One lowercase letter is assigned to each node. We define a path's value as the number of the most frequently occurring letter. For example, if letters on a path are "abaca", then the value of that path is 3. Your task is find a path whose value is the largest.

Input

The first line contains two positive integers n, m (1 ≤ n, m ≤ 300 000), denoting that the graph has n nodes and m directed edges.

The second line contains a string s with only lowercase English letters. The i-th character is the letter assigned to the i-th node.

Then m lines follow. Each line contains two integers x, y (1 ≤ x, y ≤ n), describing a directed edge from x to y. Note that x can be equal to y and there can be multiple edges between x and y. Also the graph can be not connected.

Output

Output a single line with a single integer denoting the largest value. If the value can be arbitrarily large, output -1 instead.

Examples

Input

5 4
abaca
1 2
1 3
3 4
4 5


Output

3


Input

6 6
xzyabc
1 2
3 1
2 3
5 4
4 3
6 4


Output

-1


Input

10 14
xzyzyzyzqx
1 2
2 4
3 5
4 5
2 6
6 8
6 5
2 10
3 9
10 9
4 6
1 10
2 8
3 7


Output

4

Note

In the first sample, the path with largest value is 1 → 3 → 4 → 5. The value is 3 because the letter 'a' appears 3 times.
/*
ЗАПУСКАЕМ ВЫСОКОГО
░ГУСЯ░▄▀▀▀▄░РАБОТЯГИ░░
▄███▀░◐░░░▌░░░░░░░
░░░░▌░░░░░▐░░░░░░░
░░░░▐░░░░░▐░░░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░▄▀▒▒▀▀▀▀▄
░░░▐░░░░▐▒▒▒▒▒▒▒▒▀▀▄
░░░▐░░░░▐▄▒▒▒▒▒▒▒▒▒▒▀▄
░░░░▀▄░░░░▀▄▒▒▒▒▒▒▒▒▒▒▀▄
░░░░░░▀▄▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▀▄
░░░░░░░░░░░▌▌░▌▌░░░░░
░░░░░░░░░░░▌▌░▌▌░░░░░
░░░░░░░░░▄▄▌▌▄▌▌░░░░░
 */

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

public class Main {
    List<Integer> g[];
    List<Integer> rg[];

    void solve() throws IOException {
        int n = readInt(), m = readInt();
        char[] c = readString().toCharArray();
        g = new List[n];
        rg = new List[n];
        for (int i = 0; i < n; i++) {
            g[i] = new ArrayList<>();
            rg[i] = new ArrayList<>();
        }
        for (int i = 0; i < m; i++) {
            int f = readInt() - 1;
            int t = readInt() - 1;
            g[f].add(t);
            rg[t].add(f);
        }
        used = new boolean[n];
        topSort = new ArrayList<>();
        topSort();
        boolean ans = false;
        Arrays.fill(used, false);
        cl = new int[n];
        for (int i : topSort) {
            if (!used[i]) {
                ans |= dfsC(i);
            }
        }
        if (ans) {
            out.println(-1);
            return;
        }
        int[][] ch = new int[n][26];
        for (int i : topSort) {
            for (int j : rg[i]) {
                for (int k = 0; k < 26; k++) {
                    ch[i][k] = maxInt(ch[j][k], ch[i][k]);
                }
            }
            ch[i][c[i] - 'a']++;
        }
        int answer = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 26; j++) {
                answer = maxInt(answer, ch[i][j]);
            }
        }
        out.println(answer);
    }

    boolean[] used;
    int[] cl;

    boolean dfsC(int from) {
        cl[from] = 1;
        boolean answer = false;
        for (int i : g[from]) {
            if (cl[i] == 0) {
                if (dfsC(i)) return true;
            } else if (cl[i] == 1) {
                return true;
            }
        }
        cl[from] = 2;
        return false;
    }

    ArrayList<Integer> topSort;

    void dfs(int from) {
        used[from] = true;
        for (int i : g[from]) {
            if (!used[i]) {
                dfs(i);
            }
        }
        topSort.add(from);
    }

    void topSort() {
        Arrays.fill(used, false);
        topSort.clear();
        for (int i = 0; i < g.length; i++) {
            if (!used[i]) {
                dfs(i);
            }
        }
        Collections.reverse(topSort);
    }

    public static void main(String[] args) throws IOException {
        new Main().run();
    }

    BufferedReader in;
    PrintWriter out;
    StringTokenizer tok;

    Main() throws FileNotFoundException {
        try {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        } catch (Exception e) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        }
        tok = new StringTokenizer("");
    }

    void run() throws IOException {
        solve();
        out.close();
    }


    class Fenwik {
        private long[] t;
        private int length;

        Fenwik(int[] a) {
            this.length = a.length + 100;
            this.t = new long[length];
            for (int i = 0; i < a.length; ++i) this.inc(i, a[i]);
        }

        void inc(int i, int delta) {
            for (; i < this.length; i = i | (i + 1)) t[i] += delta;
        }

        long getSum(int r) {
            long sum = 0;
            for (; r >= 0; r = (r & (r + 1)) - 1) sum += this.t[r];
            return sum;
        }
    }

    String delimiter = " ";

    String readLine() throws IOException {
        return in.readLine();
    }

    String readString() throws IOException {
        while (!tok.hasMoreTokens()) {
            String nextLine = readLine();
            if (null == nextLine) return null;
            tok = new StringTokenizer(nextLine);
        }
        return tok.nextToken(delimiter);
    }

    int readInt() throws IOException {
        return Integer.parseInt(readString());
    }

    long readLong() throws IOException {
        return Long.parseLong(readString());
    }

    double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }

    int[] readIntArray(int b) {
        int a[] = new int[b];
        for (int i = 0; i < b; i++)
            try {
                a[i] = readInt();
            } catch (IOException e) {
                e.printStackTrace();
            }
        return a;
    }

    int[] readSortedIntArray(int size) throws IOException {
        Integer[] array = new Integer[size];
        for (int index = 0; index < size; ++index) array[index] = readInt();
        Arrays.sort(array);
        int[] sortedArray = new int[size];
        for (int index = 0; index < size; ++index) sortedArray[index] = array[index];
        return sortedArray;
    }

    int[] sortedIntArray(int size, int[] array) throws IOException {
        for (int index = 0; index < size; ++index) array[index] = readInt();
        Arrays.sort(array);
        int[] sortedArray = new int[size];
        for (int index = 0; index < size; ++index) sortedArray[index] = array[index];
        return sortedArray;
    }

    int minInt(int... values) {
        int min = Integer.MAX_VALUE;
        for (int value : values) min = Math.min(min, value);
        return min;
    }

    int maxInt(int... values) {
        int max = Integer.MIN_VALUE;
        for (int value : values) max = Math.max(max, value);
        return max;
    }

    long minLong(long... values) {
        long min = Long.MAX_VALUE;
        for (long value : values) min = Math.min(min, value);
        return min;
    }

    long maxLong(long... values) {
        long max = Long.MIN_VALUE;
        for (long value : values) max = Math.max(max, value);
        return max;
    }

    boolean checkIndex(int index, int size) {
        return (0 <= index && index < size);
    }

    int abs(int a) {
        if (a < 0) return -a;
        return a;
    }
}