#include <bits/stdc++.h>
using namespace std;
int n, m;
int namenod[300007];
bool root[300007];
vector<vector<int>> adj;
set<int> roots;
vector<int> topological;
int color[300007] = {0};
bool nocyc(int x) {
  bool b = true;
  for (auto nxt : adj[x]) {
    if (color[nxt] == 0)
      color[nxt] = 1, b &= nocyc(nxt);
    else if (color[nxt] == 1) {
      return 0;
    }
  }
  color[x] = 2;
  return b;
}
void toposon(int nod, bool vis[], stack<int> &stk) {
  vis[nod] = 1;
  for (auto nxt : adj[nod]) {
    if (!vis[nxt]) {
      toposon(nxt, vis, stk);
    }
  }
  stk.push(nod);
}
void topo() {
  stack<int> stk;
  bool vis[300007] = {};
  for (int i = 1; i <= n; ++i) {
    if (!vis[i]) {
      toposon(i, vis, stk);
    }
  }
  while (!stk.empty()) {
    topological.push_back(stk.top());
    stk.pop();
  }
}
int main() {
  cin >> n >> m;
  adj.resize(n + 3);
  string s;
  cin >> s;
  for (int i = 0; i < n; ++i) {
    namenod[i + 1] = s[i] - 'a';
  }
  int x, y;
  for (int i = 1; i <= n; ++i) root[i] = 1;
  for (int i = 0; i < m; ++i) {
    scanf("%d%d", &x, &y);
    if (x == y) return puts("-1"), 0;
    adj[x].push_back(y);
    root[y] = 0;
  }
  for (int r = 1; r <= n; ++r) {
    roots.insert(r);
    if (!nocyc(r)) return puts("-1"), 0;
  }
  topo();
  int dis[300007];
  int greed = 0;
  for (int c = 0; c < 26; ++c) {
    memset(dis, -1, sizeof dis);
    for (auto r : roots) {
      namenod[r] != c ? dis[r] = 0 : dis[r] = 1;
    }
    for (int i = 0; i < n; ++i) {
      int nod = topological[i];
      if (dis[nod] != -1) {
        for (auto nxt : adj[nod]) {
          int tem = 0;
          if (namenod[nxt] == c) tem++;
          if (dis[nod] + tem > dis[nxt]) dis[nxt] = dis[nod] + tem;
        }
      }
    }
    for (int i = 1; i <= n; ++i) {
      greed = max(greed, dis[i]);
    }
  }
  cout << greed;
}
