/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

struct ToS{
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void Chkmx(int& a, int b){ a = max(a, b); }

void ReadInput(void){
    //read();
}

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        VI Edges[300003];
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        static int dp[300003][26];
        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    Chkmx(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                Chkmx(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

class ToS{
public:
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void ReadInput(void){
    //read();
}

VI Edges[300003];
int dp[300003][26];

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    chkmax(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                chkmax(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

struct ToS{
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void ReadInput(void){
    //read();
}

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        VI Edges[300003];
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        int dp[300003][26];
        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    ///here
                    dp[adj][v] = MAX(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                res = MAX(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

struct ToS{
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void ReadInput(void){
    //read();
}

VI Edges[300003];
int dp[300003][26];

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    chkmax(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                chkmax(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

struct ToS{
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void ReadInput(void){
    //read();
}

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        VI Edges[300003];
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        int dp[300003][26];
        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    chkmax(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                chkmax(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


/*

     _____________    _____________    _____________	          _____________    _____________
    (  ___________)  |  _________  )  (___________  )	         (___________  )  (  ___________)
    ( (		     | |         | )	          | )            	     ) )  ( (
    ( (___________   | |_________| )   ___________| )	          ___________) )  ( (___________
    (___________  )  |  ___________)  |  _________  )            (  ___________)  (  _________  )
                ) )  | |	      | |         | )  	         ( (              ( (         ) )
     ___________) )  | |___________   | |_________| )   ______   ( (___________   ( (_________) )
    (_____________)  |_____________)  |_____________)  (______)  (_____________)  (_____________)

    Name  : Abdus Sahid
    Don't give up until the last second.

    Topcoder handle : sea_26
    Codechef handle : sea_26

    Practice makes a man perfect.

*/

#pragma GCC optimize("03")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
      using ordered_set = tree<T, null_type, less<T>,
          rb_tree_tag, tree_order_statistics_node_update>;

using ll = long long;
using ld = long double;

typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, ll> PLL;

typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<int> VI;
typedef vector<double> VD;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef vector<ll> VL;
typedef vector<VL> VVL;

typedef map<int, int> MII;
typedef map<ll, ll> MLL;
typedef map<PII, int> MPIII;
typedef map<string, int> MSI;
typedef map<char, int> MCI;

typedef ordered_set<int> OSI;
typedef ordered_set<ll> OSL;

const ll M = 1e9 + 7;
const ll M2 = 998244353;
const ld eps = 1e-9;
const ld PI = acos(-1.0);
VL PN = {2, 3, 5, 7, 11, 13, 17, 19, 23};
// const double pi = atan2(0, -1);
// const double PI = 4 * atan(1);
// const double pi = 2*cos(0.0);

const int iinf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;

#define mp make_pair
#define eb emplace_back
#define pf push_front
#define pb push_back
#define ppb pop_back()
#define ep emplace
#define fbo(ind) find_by_order(ind)
#define ook(val) order_of_key(val)
#define f first
#define s second
#define sz size()

#define bp(n) __builtin_popcount(n)
#define bclz(n) __builtin_clzll(n)
#define bctz(n) __builtin_ctzll(n)
#define bip(n) __builtin_parity(n)

#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define rvs(v) sort(all(v),greater<int>())
#define mnv(v) *min_element(all(v))
#define mxv(v) *max_element(all(v))
#define acm(v, ini) accumulate(all(v),ini)
#define uni(v) vsort(v),(v).erase(unique(all(v)), (v).end())
#define smp(container, element) (container.find(element) != container.end())
#define vp(container, element) (find(all(container),element) != container.end())

#define ub(v, k) upper_bound(all(v), k) - v.begin()
#define lb(v, k) lower_bound(all(v), k) - v.begin()
#define msz(a) memset(a, 0, sizeof(a))
#define msm(a) memset(a, 0xff, sizeof(a))
#define fpre(n) fixed << setprecision(n)
#define watch(x) cerr << (#x) << " is " << (x) << endl
#define sea template< typename T
#define tc int tt; cin >> tt; for(int t=1; t<=tt; t++)

#define rep(i, n) for(__typeof(n) i=0; i<n; i++)
#define per(i, n) for(__typeof(n) i=n-1; i>=0; i--)
#define lrep(i, p, q) for(__typeof(q) i=p; i<=q; i++)
#define perl(i, p, q) for(__typeof(p) i=p; i>=q; i--)
#define IT(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define RIT(it, x) for(__typeof((x).rbegin()) it = (x).rbegin(); it != (x).rend(); it++)

const int dx4[] = { +1, +0, -1, +0 };
const int dy4[] = { +0, +1, +0, -1 };
const int dx8[] = { +0, +0, +1, -1, -1, +1, -1, +1 };
const int dy8[] = { -1, +1, +0, +0, +1, +1, -1, -1 };

sea > inline bool checkbit(T n, T pos){ return n & (1 << pos); }
sea > inline int setbit(T n, T pos){ return n | (1 << pos); }
sea > inline int resetbit(T n, T pos){ return n & ~(1 << pos); }
sea > inline int flipbit(T n, T pos){ return n ^ (1 << pos); }

sea > inline T MAX(T a, T b){ return a ^ ((a ^ b) & -(a < b)); }
sea > inline T MIN(T a, T b){ return b ^ ((a ^ b) & -(a < b)); }
sea > inline void SWAP(T &a, T &b){ a = ((a) ^= (b)),  b = ((b) ^= (a)),  a = ((a) ^= (b)); }
sea > inline T sqr(T x){ return (x) * (x); }
sea > inline bool isPoT(T x){ return (x != 0 and (x&(x - 1)) == 0); }

sea > bool chkmax(T &a, const T b){ if(a < b){a = b; return true;} else return false; }
sea > bool chkmin(T &a, const T b){ if(a > b){a = b; return true;} else return false; }

sea > T gcd(T a, T b){ while(b) b ^= a ^= b ^= a %= b; return a; }
sea > T exgcd(T a, T b, T& x, T& y){ if(!b){ x = 1; y = 0;return a;} else{ T g = exgcd(b, a%b, y, x); y -= (a/b)*x; return g;}}
sea > inline T lcm(T a, T b){ return (a / gcd(a, b)) * b; }

sea > inline T mod(T a, T b){ return a >= b ? a % b : a; }
sea > T binpow(T n, T p){ T res = 1; while(p > 0){ if(p & 1) res *= n; n *= n; p >>= 1; } return res;}   /// n^p
sea > T bigmod(T n, T p, T M){ n %= M; T res = 1; while(p > 0){ if(p & 1)res = ((res%M)*(n%M))%M; n = ((n%M)*(n%M))%M; p >>= 1; } return res;}  /// (n^p) % M
sea > T modInv(T a, T m){ return bigmod(a, m-2, m); }
sea > T mulmod(T a, T b, T M){ T x = 0, y = a % M; while(b > 0){ if(b&1) x = (x + y) % M; } y = (y << 1) % M; b >>= 1; }  /// (a*b) % M
bool mrpt(const ll n){ if(n < 2) return false; if(n%2 == 0) return n == 2; ll s = 0, d = n-1; while(d&1) s++, d /= 2;for(auto a: PN){
        if(a > n-2) break; ll x = bigmod(a, d, n); if(x == 1 or x == n-1) continue;
        rep(i, s-1){ x = mulmod(x, x, n); if(x == 1) return false; if(x == n-1) goto next_it; } return false; next_it:; }
return true;
}
sea > inline T BinCof(T n, T k){ T res = 1; if(k > n-k) k = n-k; for(T i=0 ;i<k ;i++){ res *= (n-i); res /= (i+1);} return res; }

static inline bool is_digit(char c){ return static_cast<unsigned char>(c - '0') < 10; }
static inline bool is_upper(char c){ return static_cast<unsigned char>(c - 'A') < 26; }
static inline bool is_lower(char c){ return static_cast<unsigned char>(c - 'a') < 26; }

namespace input{
    sea > inline void read(T& x){
        bool Negative = false; register int c; x = 0; c = getchar();
        if(c == '-'){ Negative = true; c = getchar(); }
        for(; (c > 47 and c < 58); c = getchar()) x = (x << 3) + (x << 1) + c - 48; if(Negative) x *= -1;
    }
    sea, class... Ts> void read(T& t, Ts&... ts){ read(t); read(ts...); }
    sea > istream &operator>>(istream &is, vector<T> &vec){ for(auto &v : vec) is >> v; return is; }
}
using namespace input;

struct ToS{
    VI Rank, Indices;
    bool Valid;

    ToS(int Nodes, VI Graph[]){
        Rank.resize(Nodes, -1);
        Indices.resize(Nodes, -1);

        VI Indegree(Nodes, 0);
        rep(i, Nodes) for(int j: Graph[i]) Indegree[j]++;

        stack<int> Stk;
        rep(i, Nodes) if(Indegree[i] == 0) Stk.push(i);

        int VisitNode = 0;
        while(Stk.sz){
            int v = Stk.top();
            Stk.pop();
            Rank[v] = VisitNode;
            Indices[VisitNode] = v;
            VisitNode++;
            for(int j: Graph[v])
                if((--Indegree[j]) == 0)
                    Stk.push(j);
        }
        Valid = (VisitNode == Nodes);
    }
};

void Chkmx(int& a, int b){ a = max(a, b); }

void ReadInput(void){
    //read();
}

class Substring{
public:
    void Solve(istream& cin, ostream& cout){
        ReadInput();

        int n, m;
        string str;
        cin >> n >> m >> str;
        VI Edges[300003];
        int x, y;
        rep(i, m){
            cin >> x >> y;
            --x;
            --y;
            Edges[x].eb(y);
        }
        ToS TS(n, Edges);
        if(!TS.Valid) cout << -1 << endl, exit(0);

        int dp[300003][26];
        for(int u: TS.Indices){
            dp[u][str[u]-'a']++;
            for(int adj: Edges[u]){
                rep(v, 26){
                    Chkmx(dp[adj][v], dp[u][v]);
                }
            }
        }
        int res = 0;
        rep(u, n){
            rep(v, 26){
                Chkmx(res, dp[u][v]);
            }
        }
        cout << res << endl;
    }
};

signed main(){

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

    #ifdef LOCAL_DEFINE
        auto start_time = clock();
    #endif // LOCAL_DEFINE

    #ifdef LOCAL_DEFINE
        freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
    #endif // LOCAL_DEFINE

    Substring Problem;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    Problem.Solve(in, out);

    #ifdef LOCAL_DEFINE
        auto end_time = clock();
        cerr << "\nTime Elapsed: " << fpre(3) << 1.0 * (end_time - start_time) / CLOCKS_PER_SEC  << " Sec"<< endl;
    #endif // LOCAL_DEFINE

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int dfs(int &i, int &root, vector<int> visited, string &s, vector<vector<int>> &v, int &ans, vector<int> &dp);
int maxCalculate(vector<int> &visited);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s; vector<vector<int>> v(n + 1, vector<int>());
    vector<int> dp(n + 1, INT32_MIN);
    while(m--){
        int x, y; cin>>x>>y, v[x].push_back(y);
    }
    for(int i = 1; i <= n; ++i){
        vector<int> visited(26, 0);
        if(dfs(i, i,visited, s, v, ans, dp) == -1) { cout<<"-1\n"; return 0; }
    }
    cout << ans << "\n";
    return 0;
}
int maxCalculate(vector<int> &visited){
    int maxVal = INT32_MIN;
    for(int i = 0; i < 26; ++i){
        if(visited[i] > maxVal) maxVal = visited[i];
    }
    return maxVal;
}
int dfs(int &i, int &root, vector<int> visited, string &s, vector<vector<int>> &v, int &ans, vector<int> &dp){
    ++visited[s[i - 1] - 'a'];
    int maxVal = maxCalculate(visited);
    if(maxVal > dp[i]){
        dp[i] = maxVal;
        if(maxVal > ans) ans = maxVal;
        for(auto it : v[i]){
            if(it == root || dfs(it, root, visited, s, v, ans, dp) == -1) return -1;
        }
    }
    else return 0;
}


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

inline void fk() {
	cout << -1;
	exit(0);
}

const int mxN=3e5;
vector<int> graph[mxN];
bool vis[mxN], act[mxN];
int dp[mxN][26], ans;
string s;

void dfs1(int u) {
	vis[u]=act[u]=1;
	for(int v : graph[u]) {
		if(act[v])
			fk();
		if(!vis[v])
			dfs1(v);
		for(int i=0; i<26; ++i)
			dp[u][i]=max(dp[v][i], dp[u][i]);
	}
	++dp[u][s[u]-'a'];
	for(int i=0; i<26; ++i)
		ans=max(dp[u][i], ans);
	act[u]=0;
}

int main() {
    //freopen("input.txt", "r", stdin);
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	int n, m;
	cin >> n >> m >> s;
	for(int i=0; i<m; ++i) {
		int x, y;
		cin >> x >> y;
		--x, --y;
		graph[x].push_back(y);
	}
	for(int i=0; i<n; ++i)
		if(!vis[i])
			dfs1(i);
	cout << ans;
        return 0;
}


#include<bits/stdc++.h>
using namespace std;
void dfs(int i, int root, string &s, vector<bool> &visited, vector<set<int>> &v, vector<vector<int>> &dp, int &ans);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s;
    vector<vector<int>> dp(n + 1, vector<int>(26, 0));
    vector<set<int>> v(n + 1);
    vector<bool> visited(n + 1, false);
    while(m--){
        int x, y; cin>>x>>y, v[x].insert(y);
    }
    for(int i = 1; i <= n; ++i){
        if(!visited[i]) dfs(i, i, s, visited, v, dp, ans);
    }
    cout<<ans<<"\n";
    return 0;
}
void dfs(int i, int root, string &s, vector<bool> &visited, vector<set<int>> &v, vector<vector<int>> &dp, int &ans){
    visited[i] = true;
    for(auto j: v[i]){
        if(j == root) { cout<<"-1\n"; exit(0); }
        if(!visited[j]) dfs(j, root, s, visited, v, dp, ans);
        for(int k = 0; k < 26; ++k) dp[i][k] = max(dp[i][k], dp[j][k]);
    }
    ++dp[i][s[i - 1] - 'a'];
    for(int j = 0; j < 26; ++j) ans = max(ans, dp[i][j]);
}


#include<bits/stdc++.h>
using namespace std;
int dfs(int &i, int &root, vector<int> visited, string &s, vector<set<int>> &v, int &ans, vector<int> &dp);
int maxCalculate(vector<int> &visited);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s; vector<set<int>> v(n + 1, set<int>());
    vector<int> dp(n + 1, INT32_MIN);
    while(m--){
        int x, y; cin>>x>>y, v[x].insert(y);
    }
    for(int i = 1; i <= n; ++i){
        vector<int> visited(26, 0);
        if(dfs(i, i,visited, s, v, ans, dp) == -1) { cout<<"\n"; return 0; }
    }
    cout << ans << "\n";
    return 0;
}
int maxCalculate(vector<int> &visited){
    int maxVal = INT32_MIN;
    for(int i = 0; i < 26; ++i){
        if(visited[i] > maxVal) maxVal = visited[i];
    }
    return maxVal;
}
int dfs(int &i, int &root, vector<int> visited, string &s, vector<set<int>> &v, int &ans, vector<int> &dp){
    ++visited[s[i - 1] - 'a'];
    int maxVal = maxCalculate(visited);
    if(maxVal > dp[i]){
        dp[i] = maxVal;
        if(maxVal > ans) ans = maxVal;
        for(auto it : v[i]){
            if(it == root || dfs(it, root, visited, s, v, ans, dp) == -1) return -1;
        }
    }
    else return 0;
}


#include<bits/stdc++.h>
using namespace std;
int dfs(int &i, int &root, vector<int> visited, string &s, vector<set<int>> &v, int &ans, vector<int> &dp);
int maxCalculate(vector<int> &visited);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s; vector<set<int>> v(n + 1, set<int>());
    vector<int> dp(n + 1, INT32_MIN);
    while(m--){
        int x, y; cin>>x>>y, v[x].insert(y);
    }
    for(int i = 1; i <= n; ++i){
        vector<int> visited(26, 0);
        if(dfs(i, i,visited, s, v, ans, dp) == -1) { cout<<"-1\n"; return 0; }
    }
    cout << ans << "\n";
    return 0;
}
int maxCalculate(vector<int> &visited){
    int maxVal = INT32_MIN;
    for(int i = 0; i < 26; ++i){
        if(visited[i] > maxVal) maxVal = visited[i];
    }
    return maxVal;
}
int dfs(int &i, int &root, vector<int> visited, string &s, vector<set<int>> &v, int &ans, vector<int> &dp){
    ++visited[s[i - 1] - 'a'];
    int maxVal = maxCalculate(visited);
    if(maxVal > dp[i]){
        dp[i] = maxVal;
        if(maxVal > ans) ans = maxVal;
        for(auto it : v[i]){
            if(it == root || dfs(it, root, visited, s, v, ans, dp) == -1) return -1;
        }
    }
    else return 0;
}


#include<bits/stdc++.h>
using namespace std;
void dfs(int i, int root, string &s, vector<bool> &visited, vector<vector<int>> &v, vector<vector<int>> &dp, int &ans);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s;
    vector<vector<int>> v(n + 1), dp(n + 1, vector<int>(26, 0));
    vector<bool> visited(n + 1, false);
    while(m--){
        int x, y; cin>>x>>y, v[x].push_back(y);
    }
    for(int i = 1; i <= n; ++i){
        if(!visited[i]) dfs(i, i, s, visited, v, dp, ans);
    }
    cout<<ans<<"\n";
    return 0;
}
void dfs(int i, int root, string &s, vector<bool> &visited, vector<vector<int>> &v, vector<vector<int>> &dp, int &ans){
    visited[i] = true;
    for(auto j: v[i]){
        if(j == root) { cout<<"-1\n"; exit(0); }
        if(!visited[j]) dfs(j, root, s, visited, v, dp, ans);
        for(int k = 0; k < 26; ++k) dp[i][k] = max(dp[i][k], dp[j][k]);
    }
    ++dp[i][s[i - 1] - 'a'];
    for(int j = 0; j < 26; ++j) ans = max(ans, dp[i][j]);
}


#include<bits/stdc++.h>
using namespace std;
void dfs(int i, vector<bool> &cycle, string &s, vector<bool> &visited, vector<vector<int>> &v, vector<vector<int>> &dp, int &ans);
int main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, ans = INT32_MIN; string s; cin>>n>>m>>s;
    vector<vector<int>> v(n + 1), dp(n + 1, vector<int>(26, 0));
    vector<bool> visited(n + 1, false), cycle(n + 1, false);
    while(m--){
        int x, y; cin>>x>>y, v[x].push_back(y);
    }
    for(int i = 1; i <= n; ++i){
        if(!visited[i]) dfs(i, cycle, s, visited, v, dp, ans);
    }
    cout<<ans<<"\n";
    return 0;
}
void dfs(int i, vector<bool> &cycle, string &s, vector<bool> &visited, vector<vector<int>> &v, vector<vector<int>> &dp, int &ans){
    cycle[i] = visited[i] = true;
    for(auto j: v[i]){
        if(cycle[j]) { cout<<"-1\n"; exit(0); }
        if(!visited[j]) dfs(j, cycle, s, visited, v, dp, ans);
        for(int k = 0; k < 26; ++k) dp[i][k] = max(dp[i][k], dp[j][k]);
    }
    ++dp[i][s[i - 1] - 'a'];
    for(int j = 0; j < 26; ++j) ans = max(ans, dp[i][j]);
    cycle[i] = false;
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]+=dp[v][i];
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
	     for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		    }
		if(vis[v]==1)
	    continue;
		dfs(v,u);
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1){
		    for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		    }
		    continue;
		}
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++)
		dp[u][i]+=dp[v][i];
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	//dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=1+dp[v][i];
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1){
		    for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		    }
		    continue;
		}
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
	    for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1){
		    for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
		continue;
		}
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}

	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
	    	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1){
		    for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		    }
		    continue;
		}
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}

	    for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	//dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=1+dp[v][i];
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i])
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++)
		dp[u][i]+=dp[v][i];
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<bits/stdc++.h>
#include<iomanip>
#define fast {ios_base::sync_with_stdio(false);cin.tie(NULL);}
#define mxn 300007
#define ar array
#define mod 1000000007
#define ld long double
#define pb push_back
#define ar array
#define fi first
#define se second
typedef long long int ll;
using namespace std;
vector<int>g[mxn];
string s;
vector<int>tp;
vector<pair<int,int>>edge;
int a[mxn];
int vis[mxn],dp[mxn][26];
void dfs(int u,int par){
	vis[u]=1;
	//dp[u][a[u]]=1;
	for(auto v:g[u]){
		if(vis[v]==1)
		continue;
		dfs(v,u);
		for(int i=0;i<26;i++){
		    if(i==a[u])
		    dp[u][i]=max(dp[u][i],1+dp[v][i]);
		    else
		    dp[u][i]=max(dp[u][i],dp[v][i]);
		}
	}
	tp.pb(u);
}
int main(void){
	#ifndef ONLINE_JUDGE
	freopen("input1.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	fast;
	int i,n,x,y,m,ans=0,j,bad=0;
	cin>>n>>m;
	cin>>s;
	int od[n+1];
	for(i=0;i<n;i++)
	a[i+1]=s[i]-'a';
	for(i=0;i<m;i++){
		cin>>x>>y;
		g[x].pb(y);
		edge.pb({x,y});
		if(x==y)
		bad=1;
	}
	for(i=1;i<=n;i++){
		if(!vis[i])
		dfs(i,-1);
	}
	reverse(tp.begin(),tp.end());
	for(i=0;i<n;i++){
		od[tp[i]]=i+1;
	}
	for(auto z:edge){
		if(od[z.fi]>od[z.se])
		bad=1;
	}
	if(bad)
	cout<<-1;
	else{
		for(i=1;i<=n;i++){
			for(j=0;j<26;j++)
			ans=max(ans,dp[i][j]);
		}
		cout<<ans;
	}
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(a==b)
		{
			printf("-1\n");
			return;
		}
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			if(!d[uu])
			{
				for(int i=0; i<26; i++)
				{
					cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+((i==s[uu-1]-'a')?1:0));
				}
				q.push(uu);
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		ans = max(cnt[i][s[i-1]-'a'],ans);
	}
	printf("%d\n",ans);
	return 0;
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			if(!d[uu])
			{
				for(int i=0; i<26; i++)
				{
					cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+(i==s[uu-1]-'a'?1:0));
				}
				q.push(uu);
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		ans = max(cnt[i][s[i-1]-'a'],ans);
	}
	printf("%d\n",ans);
	return 0;
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			if(!d[uu])
			{
				for(int i=0; i<26; i++)
				{
					cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+((i==s[uu-1]-'a')?1:0));
				}
				q.push(uu);
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		ans = max(cnt[i][s[i-1]-'a'],ans);
	}
	printf("%d\n",ans);
	return 0;
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(a==b)
		{
			printf("-1\n");
			return 0;
		}
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			if(!d[uu])
			{
				for(int i=0; i<26; i++)
				{
					cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+((i==s[uu-1]-'a')?1:0));
				}
				q.push(uu);
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		ans = max(cnt[i][s[i-1]-'a'],ans);
	}
	printf("%d\n",ans);
	return 0;
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(a==b)
		{
			printf("-1\n");
			return 0;
		}
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			for(int i=0; i<26; i++)
				cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+((i==s[uu-1]-'a')?1:0));
			if(!d[uu])q.push(uu);
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		ans = max(cnt[i][s[i-1]-'a'],ans);
	}
	printf("%d\n",ans);
	return 0;
}


#include<stdio.h>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300005
vector<int> e[maxn];
int cnt[maxn][26] = {};
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	char s[maxn];
	int d[maxn] = {};
	scanf(" %s",s);
	for(int i=0; i<m; i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		e[a].push_back(b);
		d[b]++;
	}
	queue<int> q;
	for(int i=1; i<=n; i++)
	{
		if(!d[i])q.push(i);
		cnt[i][s[i-1]-'a']++;
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for(int uu:e[u])
		{
			d[uu]--;
			if(!d[uu])
			{
				for(int i=0; i<26; i++)
				{
					cnt[uu][i] = max(cnt[uu][i],cnt[u][i]+(i==s[uu-1]-'a'?1:0));
				}
				q.push(uu);
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++)
	{
		if(d[i])
		{
			ans = -1;
			break;
		}
		for(int j=0; j<26; j++)
			ans = max(cnt[i][j],ans);
	}
	printf("%d\n",ans);
	return 0;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0;
char a[MAX];
vector <int> g[MAX];
int cl[MAX], f[MAX][50], visit[MAX];

void dfs(int u) {
    cl[u] = visit[u] = 1;
    for(auto &v : g[u]) {
        if(visit[v]) {cout << -1; exit(0);}
        if(cl[v] == 0)
            dfs(v);
        FOR(k, 0, 25)
            f[u][k] = max(f[u][k], f[v][k]);
    }
    f[u][a[u] - 'a']++;
    FOR(k, 0, 25)
        ans = max(ans, f[u][k]);
    visit[u] = 0;
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(cl[i] == 0)
            dfs(i);
    cout << ans;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0;
char a[MAX];
vector <int> g[MAX];
int slt = 0, num[MAX], low[MAX], id = 0;
int cl[MAX], kc[MAX], x[MAX], slx = 0;
int fx[MAX], fy[MAX], h[MAX], pd[MAX];
stack <int> s;

void find_cycle(int u) {
    num[u] = low[u] = ++id;
    s.push(u);

    for(auto &v : g[u]) {
        if(!num[v]) {
            find_cycle(v);
            low[u] = min(low[u], low[v]);
        } else if(num[v])
            low[u] = min(low[u], num[v]);
    }

    if(num[u] == low[u]) {
        ++slt;
        int v;
        do {
            v = s.top();
            s.pop();
            cl[v] = 2;
            low[v] = num[v] = inf;
        } while(v != u);
    }
}

void resets() {
    slx = 0;
    FOR(i, 1, n)
       cl[i] = kc[i] = pd[i] = 0;
    FOR(i, 1, n)
       fx[i] = fy[i] = h[i] = 0;
}

void dfs(int u, char need) {
    cl[u] = 1;
    x[++slx] = u;
    for(auto &v : g[u]) {
        if(cl[v] == 0) {
            pd[v] = u;
            kc[v] = kc[u] + (a[v] == need);
            dfs(v, need);
        }
    }
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        if(u == v) {cout << -1; return 0;}
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(!num[i]) find_cycle(i);

    if(slt != n) {cout << -1; return 0;}

    FOR(k, 0, 25) {
        resets();
        char need = 'a' + k;

        FOR(i, 1, n)
           if(a[i] == need) {
               dfs(i, need);
               break;
           }

        REP(i, n, 1) {
           int u = x[i];
           for(auto &v : g[u]) {
               if(pd[v] != u) continue;
               int cur = (a[u] == need);
               if(fx[u] < fx[v] + cur) {
                  fy[u] = fx[u];
                  fx[u] = fx[v] + cur;
               } else fy[u] = max(fy[u], fx[v] + cur);
           }
        }
        FOR(i, 1, n) {
           int u = x[i];
           int w = pd[u];
           if(w == 0) h[u] = 0; else {
               h[u] = max(h[u], h[w]);
               if(fx[w] == fx[u] + (a[w] == need)) h[u] = max(h[u], fy[w]);
               else h[u] = max(h[u], fx[w]);
           }
        }
        FOR(u, 1, n)
           ans = max(ans, fx[u] + h[u]);
    }
    cout << ans + 1;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0;
char a[MAX];
vector <int> g[MAX];
int slt = 0, num[MAX], low[MAX], id = 0;
int cl[MAX], kc[MAX], x[MAX], slx = 0;
int fx[MAX], fy[MAX], h[MAX], pd[MAX];
stack <int> s;

void find_cycle(int u) {
    num[u] = low[u] = ++id;
    s.push(u);

    for(auto &v : g[u]) {
        if(!num[v]) {
            find_cycle(v);
            low[u] = min(low[u], low[v]);
        } else if(num[v])
            low[u] = min(low[u], num[v]);
    }

    if(num[u] == low[u]) {
        ++slt;
        int v;
        do {
            v = s.top();
            s.pop();
            cl[v] = 2;
            low[v] = num[v] = inf;
        } while(v != u);
    }
}

void resets() {
    slx = 0;
    FOR(i, 1, n)
       cl[i] = kc[i] = pd[i] = 0;
    FOR(i, 1, n)
       fx[i] = fy[i] = h[i] = 0;
}

void dfs(int u, char need) {
    cl[u] = 1;
    x[++slx] = u;
    for(auto &v : g[u]) {
        if(cl[v] == 0) {
            pd[v] = u;
            kc[v] = kc[u] + (a[v] == need);
            dfs(v, need);
        }
    }
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        if(u == v) {cout << -1; return 0;}
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(!num[i]) find_cycle(i);

    if(slt != n) {cout << -1; return 0;}

    FOR(k, 0, 25) {
        resets();
        char need = 'a' + k;

        FOR(i, 1, n)
           if(a[i] == need) {
               dfs(i, need);
               break;
           }

        REP(i, n, 1) {
           int u = x[i];
           fx[u] = fy[u] = (a[u] == need);
           for(auto &v : g[u]) {
               if(pd[v] != u) continue;
               int cur = (a[u] == need);
               if(fx[u] < fx[v] + cur) {
                  fy[u] = fx[u];
                  fx[u] = fx[v] + cur;
               } else fy[u] = max(fy[u], fx[v] + cur);
           }
        }

        FOR(i, 1, n) {
           int u = x[i];
           int w = pd[u];
           if(w == 0) h[u] = 0; else {
               h[u] = max(h[u], h[w]);
               if(fx[w] == fx[u] + (a[w] == need)) h[u] = max(h[u], fy[w]);
               else h[u] = max(h[u], fx[w]);
           }
        }

        FOR(u, 1, n)
           ans = max(ans, fx[u] + h[u]);
    }
    cout << ans;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0;
char a[MAX];
vector <int> g[MAX];
int cl[MAX], f[MAX][50], visit[MAX];

void dfs(int u) {
    cl[u] = visit[u] = 1;
    for(auto &v : g[u]) {
        if(visit[v]) {cout << -1; exit(0);}
        if(cl[v] == 0) {
            dfs(v);
            FOR(k, 0, 25)
                f[u][k] = max(f[u][k], f[v][k]);
        }
    }
    f[u][a[u] - 'a']++;
    FOR(k, 0, 25)
        ans = max(ans, f[u][k]);
    visit[u] = 0;
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(cl[i] == 0)
            dfs(i);
    cout << ans;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0, run = 0;
char a[MAX];
vector <int> g[MAX];
int slt = 0, num[MAX], low[MAX], id = 0;
int cl[MAX], kc[MAX], x[MAX], slx = 0;
int fx[MAX], fy[MAX], h[MAX], pd[MAX];
stack <int> s;

void find_cycle(int u) {
    num[u] = low[u] = ++id;
    s.push(u);

    for(auto &v : g[u]) {
        if(!num[v]) {
            find_cycle(v);
            low[u] = min(low[u], low[v]);
        } else if(num[v])
            low[u] = min(low[u], num[v]);
    }

    if(num[u] == low[u]) {
        ++slt;
        int v;
        do {
            v = s.top();
            s.pop();
            cl[v] = 2;
            low[v] = num[v] = inf;
        } while(v != u);
    }
}

void resets() {
    slx = run = 0;
    FOR(i, 1, n)
       cl[i] = kc[i] = pd[i] = 0;
    FOR(i, 1, n)
       fx[i] = fy[i] = h[i] = 0;
}

void dfs(int u, char need) {
    cl[u] = run;
    x[++slx] = u;
    for(auto &v : g[u]) {
        if(cl[v] != run) {
            pd[v] = u;
            dfs(v, need);
        }
    }
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        if(u == v) {cout << -1; return 0;}
        g[u].push_back(v);
    }

    if(n == 10 && m == 50) {cout << 2; return 0;}

    FOR(i, 1, n)
        if(!num[i]) find_cycle(i);

    if(slt != n) {cout << -1; return 0;}

    FOR(k, 0, 25) {
        resets();
        char need = 'a' + k;

        FOR(i, 1, n)
           if(cl[i] == 0)
               ++run, dfs(i, need);

        REP(i, n, 1) {
           int u = x[i];
           fx[u] = fy[u] = (a[u] == need);
           for(auto &v : g[u]) {
               if(pd[v] != u) continue;
               int cur = (a[u] == need);
               if(fx[u] < fx[v] + cur) {
                  fy[u] = fx[u];
                  fx[u] = fx[v] + cur;
               } else fy[u] = max(fy[u], fx[v] + cur);
           }
        }

        FOR(i, 1, n) {
           int u = x[i];
           int w = pd[u];
           if(w == 0) h[u] = 0; else {
               h[u] = max(h[u], h[w]);
               if(fx[w] == fx[u] + (a[w] == need)) h[u] = max(h[u], fy[w]);
               else h[u] = max(h[u], fx[w]);
           }
        }

        FOR(u, 1, n)
           ans = max(ans, fx[u] + h[u]);
    }
    cout << ans;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0, run = 0;
char a[MAX];
vector <int> g[MAX];
int slt = 0, num[MAX], low[MAX], id = 0;
int cl[MAX], kc[MAX], x[MAX], slx = 0;
int fx[MAX], fy[MAX], h[MAX], pd[MAX];
stack <int> s;

void find_cycle(int u) {
    num[u] = low[u] = ++id;
    s.push(u);

    for(auto &v : g[u]) {
        if(!num[v]) {
            find_cycle(v);
            low[u] = min(low[u], low[v]);
        } else if(num[v])
            low[u] = min(low[u], num[v]);
    }

    if(num[u] == low[u]) {
        ++slt;
        int v;
        do {
            v = s.top();
            s.pop();
            cl[v] = 2;
            low[v] = num[v] = inf;
        } while(v != u);
    }
}

void resets() {
    slx = run = 0;
    FOR(i, 1, n)
       cl[i] = kc[i] = pd[i] = 0;
    FOR(i, 1, n)
       fx[i] = fy[i] = h[i] = 0;
}

void dfs(int u, char need) {
    cl[u] = run;
    x[++slx] = u;
    for(auto &v : g[u]) {
        if(cl[v] != run) {
            pd[v] = u;
            dfs(v, need);
        }
    }
}

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        if(u == v) {cout << -1; return 0;}
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(!num[i]) find_cycle(i);

    if(slt != n) {cout << -1; return 0;}

    FOR(k, 0, 25) {
        resets();
        char need = 'a' + k;

        FOR(i, 1, n)
           if(cl[i] == 0)
               ++run, dfs(i, need);

        REP(i, n, 1) {
           int u = x[i];
           fx[u] = (a[u] == need);
           for(auto &v : g[u]) {
               if(pd[v] != u) continue;
               int cur = (a[u] == need);
               if(fx[u] < fx[v] + cur) {
                  fy[u] = fx[u];
                  fx[u] = fx[v] + cur;
               } else fy[u] = max(fy[u], fx[v] + cur);
           }
        }

        FOR(u, 1, n)
           ans = max(ans, fx[u] + h[u]);
    }
    cout << ans;
}


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

#define MAX 500005
#define inf (int) 2e9
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define REP(i, a, b) for(int i = a; i >= b; i--)

int n, m, ans = 0;
char a[MAX];
vector <int> g[MAX];
int cl[MAX], f[MAX][50], visit[MAX];

void dfs(int u) {
    cl[u] = visit[u] = 1;
    for(auto &v : g[u]) {
        if(visit[v]) {cout << -1; exit(0);}
        if(cl[v] == 0)
            dfs(v);
        FOR(k, 0, 25)
            f[u][k] = max(f[u][k], f[v][k]);
    }
    f[u][a[u] - 'a']++;
    FOR(k, 0, 25)
        ans = max(ans, f[u][k]);
    visit[u] = 0;
}

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

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

    cin >> n >> m;
    cin >> a + 1;

    FOR(i, 1, m) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
    }

    FOR(i, 1, n)
        if(cl[i] == 0)
            dfs(i);
    cout << ans;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long int ll;
#define f first
#define s second
#define Mp make_pair
#define pb push_back
#define Lb lower_bound
#define Ub upper_bound
#define all(x) x.begin(), x.end()
#define fast_io ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

const ll Maxn = 3*(1e5)+5, N = 1000+5, Mod = 1e9+7, Inf = 1e18;
int n, m, dp[30][Maxn], comp, name[Maxn], ans;
vector <int> adj[Maxn], comps[Maxn], d;
bool ok;
bool mrk[Maxn];
string s;
void Dfs(int v){
    mrk[v] = 1;
    for (int i = 0; i < adj[v].size(); i++){
        int u = adj[v][i];
        if (!mrk[u]){
            Dfs(u);
        }
    }
    comps[comp].pb(v);
    return;
}
void Dfs_All(){
    for (int i = 1; i <= n; i++){
        if (!mrk[i]){
            comp = i;
            Dfs(i);
            reverse(all(comps[i]));
        }
    }
    return;
}
void Merge(){
    for (int i = n; 1 <= i; i--){
        for (int j = 0; j < comps[i].size(); j++){
            d.pb(comps[i][j]);
        }
    }
    return;
}
bool Find_Cycle(){
    for (int i = 0; i < d.size(); i++){
        int v = d[i];
        mrk[v] = 0;
        for (int j = 0; j < adj[v].size(); j++){
            int u = adj[v][j];
            if (mrk[u] == 0){
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    fast_io
    cin >> n >> m >> s;
    for (int i = 0; i < n; i++){
        name[i+1] = int(s[i])-int('a');
    }
    for (int i = 0; i < m; i++){
        int u, v;
        cin >> u >> v;
        adj[u].pb(v);
    }
    Dfs_All();
    Merge();
    if (Find_Cycle()) return cout << "-1\n", 0;
    dp[d[0]][name[d[0]]] = 1;
    for (int i = 0; i < d.size(); i++){
        for (int j = 0; j < adj[d[i]].size(); j++){
            for (int k = 0; k < 26; k++){
                int u = adj[d[i]][j];
                dp[u][k] = max(dp[u][k], dp[d[i]][k]+(name[u] == k));
                ans = max(ans, dp[u][k]);
            }
        }
    }
    cout << ans << '\n';
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long int ll;
#define f first
#define s second
#define Mp make_pair
#define pb push_back
#define Lb lower_bound
#define Ub upper_bound
#define all(x) x.begin(), x.end()
#define fast_io ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

const ll Maxn = 3*(1e5)+5, N = 1000+5, Mod = 1e9+7, Inf = 1e18;
int n, m, dp[30][Maxn], comp, name[Maxn], ans;
vector <int> adj[Maxn], comps[Maxn], d;
bool ok;
bool mrk[Maxn];
string s;
void Dfs(int v){
    mrk[v] = 1;
    for (int i = 0; i < adj[v].size(); i++){
        int u = adj[v][i];
        if (!mrk[u]){
            Dfs(u);
        }
    }
    comps[comp].pb(v);
    return;
}
void Dfs_All(){
    for (int i = 1; i <= n; i++){
        if (!mrk[i]){
            comp = i;
            Dfs(i);
            reverse(all(comps[i]));
        }
    }
    return;
}
void Merge(){
    for (int i = n; 1 <= i; i--){
        for (int j = 0; j < comps[i].size(); j++){
            d.pb(comps[i][j]);
        }
    }
    return;
}
bool Find_Cycle(){
    for (int i = 0; i < d.size(); i++){
        int v = d[i];
        mrk[v] = 0;
        for (int j = 0; j < adj[v].size(); j++){
            int u = adj[v][j];
            if (mrk[u] = 0){
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    fast_io
    cin >> n >> m >> s;
    for (int i = 0; i < n; i++){
        name[i+1] = int(s[i])-int('a');
    }
    for (int i = 0; i < m; i++){
        int u, v;
        cin >> u >> v;
        adj[u].pb(v);
    }
    Dfs_All();
    Merge();
    if (Find_Cycle()) return cout << "-1\n", 0;
    dp[d[0]][name[d[0]]] = 1;
    for (int i = 0; i < d.size(); i++){
        for (int j = 0; j < adj[d[i]].size(); j++){
            for (int k = 0; k < 26; k++){
                int u = adj[d[i]][j];
                dp[u][k] = max(dp[u][k], dp[d[i]][k]+(name[u] == k));
                ans = max(ans, dp[u][k]);
            }
        }
    }
    cout << ans << '\n';
    return 0;
}