#include <bits/stdc++.h>
using namespace std;
string to_string(const string& str) { return str; }
template <typename T>
string to_string(const set<T>& mys) {
  if (mys.empty()) return "{}";
  string ret = "{";
  for (auto el : mys) ret += to_string(el) + ", ";
  ret.pop_back(), ret.pop_back();
  ret += "}";
  return ret;
}
template <typename T>
string to_string(const pair<T, T>& pr) {
  return "(" + to_string(pr.first) + "," + to_string(pr.second) + ")";
}
template <typename T>
string to_string(const vector<T>& vc, int w) {
  if (vc.empty()) return "";
  if (w + 1 == vc.size()) return to_string(vc[w]);
  return to_string(vc[w]) + "," + to_string(vc, w + 1);
}
template <typename T>
string to_string(const vector<T>& vc) {
  return "{" + to_string(vc, 0) + "}";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
class DebugStream {
} LOG;
template <typename T>
DebugStream& operator<<(DebugStream& s, const T&) {
  return s;
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int maxN = 1e5 + 9, maxV = 1e6 + 9, MOD = 1e9 + 7, SQ = 335, lg = 20,
          bs = 17;
bool can[bs][bs][1 << bs];
string str;
int T[maxN * 2], n, p, amo[bs], tams[1 << bs];
bool good[1 << bs], adj[bs][bs];
int qry(int l, int r) {
  int ret = 0;
  for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
    if (l & 1) ret |= T[l++];
    if (r & 1) ret |= T[--r];
  }
  return ret;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> p >> str;
  for (int i = 0; i < n; i++) {
    str[i] -= 'a';
    amo[str[i]]++;
    T[i + n] = 1 << str[i];
  }
  for (int i = n - 1; i > 0; i--) T[i] = T[i << 1] | T[i << 1 | 1];
  int lst = (1 << p) - 1;
  for (int i = 0; i < p; i++)
    for (int j = 0; j < p; j++) cin >> adj[i][j];
  for (int a = 0; a < p; a++) {
    for (int b = a; b < p; b++) {
      if (adj[a][b]) continue;
      vector<int> inds;
      for (int w = 0; w < n; w++)
        if (str[w] == a || str[w] == b) inds.push_back(w);
      for (int i = 1, saiz = inds.size(); i < saiz; i++) {
        if ((str[inds[i - 1]] == a && str[inds[i]] == b) ||
            (str[inds[i - 1]] == b && str[inds[i]] == a)) {
          int betw = qry(inds[i - 1] + 1, inds[i]);
          if (!a && !b) 42;
          int oppo = lst ^ betw;
          can[a][b][oppo] = 1;
        }
      }
    }
  }
  int ans = n;
  tams[lst] = n;
  good[lst] = 1;
  for (int i = lst - 1; i >= 0; i--) {
    int zer = 0;
    while (1 << zer & i) zer++;
    tams[i] = tams[1 << zer | i] - amo[zer];
    for (; zer < p; zer++) {
      if (1 << zer & i) continue;
      for (int a = 0; a < p; a++)
        for (int b = a; b < p; b++)
          if (can[a][b][1 << zer | i]) can[a][b][i] = 1;
      good[i] |= good[1 << zer | i];
    }
    for (int a = 0; a < p; a++) {
      if (!(1 << a & i)) continue;
      for (int b = a; b < p; b++) {
        if (!(1 << b & i) || adj[a][b]) continue;
        if (can[a][b][i]) good[i] = false;
      }
    }
    if (good[i]) ans = min(ans, tams[i]);
  }
  cout << ans << '\n';
}
