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.
/*
 * PDPM IIITDM Jabalpur
 * Asutosh Rana
 */

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

public class Main {
	long MOD = 1000000007;
	InputReader in;
	BufferedReader br;
	PrintWriter out;

	public static void main(String[] args) throws java.lang.Exception {
		Main solver = new Main();
		solver.in = new InputReader(System.in);
		solver.br = new BufferedReader(new InputStreamReader(System.in));
		solver.out = new PrintWriter(System.out);
		solver.solve();
		solver.out.flush();
		solver.out.close();
	}

	char[] S;
	int[] indeg;
	int[] V;
	List[] G;
	int[][] dp;
	public void solve() {

		int tc = 1;//in.readInt();

		for (int cas = 1; cas <= tc; cas++) {
			int N = in.readInt();
			int M = in.readInt();
			S = in.readCharA();

			G = new List[N];
			for(int i=0;i<N;i++){
				G[i] = new LinkedList<>();
			}
			
			indeg = new int[N];
			for(int i=0;i<M;i++){
				int a = in.readInt()-1;
				int b = in.readInt()-1;
				
				G[a].add(b);
				indeg[b]++;
			}
			
			V = new int[N];
			for(int i=0;i<N;i++){
				if(V[i]==0){
					if(checkcycle(i)){
						out.println("-1");return;
					}
				}
			}
			
			Queue<Integer> Q = new LinkedList<>();
			for(int i=0;i<N;i++){
				if(indeg[i]==0){
					Q.add(i);
				}
			}
			
			dp = new int[N][26];
			while(!Q.isEmpty()){
				int par = Q.remove();
				dp[par][S[par]-'a']++;
				for(Object i1:G[par]){
					int cur = (int)i1;
					for(int j=0;j<26;j++){
						dp[cur][j] = Math.max(dp[cur][j], dp[par][j]);
					}
					indeg[cur]--;
					if(indeg[cur]==0){
						Q.add(cur);
					}
				}
			}
			
			int max = 0;
			for(int i=0;i<N;i++){
				for(int j=0;j<26;j++){
					max = Math.max(max, dp[i][j]);
				}
			}
			
			out.println(max);
		}

	}
	
	public boolean checkcycle(int cur){
		if(V[cur]==1){
			return true;
		}
		if(V[cur]==2)
			return false;
		V[cur]=1;
		for(Object i1:G[cur]){
			int i = (int)i1;
			if(checkcycle(i))
				return true;
		}
		V[cur]=2;
		return false;
	}

}

class InputReader {
	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public void readInt(int[] A) {
		for (int i = 0; i < A.length; i++)
			A[i] = readInt();
	}

	public long readLong() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public void readLong(long[] A) {
		for (int i = 0; i < A.length; i++)
			A[i] = readLong();
	}

	public double readDouble() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		double res = 0;
		while (!isSpaceChar(c) && c != '.') {
			if (c == 'e' || c == 'E')
				return res * Math.pow(10, readInt());
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		}
		if (c == '.') {
			c = read();
			double m = 1;
			while (!isSpaceChar(c)) {
				if (c == 'e' || c == 'E')
					return res * Math.pow(10, readInt());
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				m /= 10;
				res += (c - '0') * m;
				c = read();
			}
		}
		return res * sgn;
	}

	public char[] readCharA() {
		return readString().toCharArray();
	}

	public String readString() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public String next() {
		return readString();
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}

}