#include <bits/stdc++.h>
using namespace std;
template <typename T, typename U>
inline void smin(T &a, const U &b) {
  if (a > b) a = b;
}
template <typename T, typename U>
inline void smax(T &a, const U &b) {
  if (a < b) a = b;
}
char s[100002];
int A[17][17], num[17][100002], f[19] = {1};
vector<int> vec[17], tmp, arr;
int vst[262144], can[262144];
int flag[262144], runs;
queue<int> q;
int main() {
  int n, p;
  scanf("%d %d %s", &n, &p, s + 1);
  for (int i = 0; i < p; i++) {
    for (int j = 0; j < p; j++) {
      scanf("%d", A[i] + j);
    }
  }
  for (int i = 1; i < 19; i++) f[i] = f[i - 1] << 1;
  for (int i = 1, c; i <= n; i++) {
    c = s[i] - 'a';
    vec[c].push_back(i);
    for (int j = 17; j--;) num[j][i] += num[j][i - 1];
    num[c][i]++;
  }
  int mx = f[p] - 1;
  for (int i = 0; i < p; i++) {
    for (int j = i; j < p; j++)
      if (!A[i][j]) {
        tmp.clear();
        if (i == j) {
          for (int k = 0, N = vec[i].size(); k < N; k++) {
            tmp.push_back(vec[i][k]);
          }
        } else {
          int I = 0, NI = vec[i].size();
          int J = 0, NJ = vec[j].size();
          while (1) {
            if (I == NI) {
              if (J == NJ) break;
              tmp.push_back(vec[j][J++]);
            } else if (J == NJ)
              tmp.push_back(vec[i][I++]);
            else {
              if (vec[i][I] > vec[j][J])
                tmp.push_back(vec[j][J++]);
              else
                tmp.push_back(vec[i][I++]);
            }
          }
        }
        arr.clear();
        int now = f[i] | f[j], all = mx ^ now;
        for (int k = 1, N = tmp.size(); k < N; k++) {
          int Pre = tmp[k - 1], Now = tmp[k] - 1, val = 0;
          for (int I = 17; I--;)
            if (num[I][Now] - num[I][Pre]) val |= f[I];
          arr.push_back(all ^ val);
        }
        sort(arr.begin(), arr.end());
        arr.resize(unique(arr.begin(), arr.end()) - arr.begin());
        runs++;
        q = queue<int>();
        for (int k = arr.size(); k--;) {
          q.push(arr[k]);
          flag[arr[k]] = runs;
        }
        while (!q.empty()) {
          int U = q.front();
          q.pop();
          for (int k = 0, u = U; k < 17; k++, u >>= 1)
            if (u & 1) {
              int v = U ^ f[k];
              if (flag[v] != runs) {
                flag[v] = runs;
                q.push(v);
              }
            }
        }
        for (int k = all;; k = all & (k - 1)) {
          if (flag[k] == runs) vst[k | now] = 1;
          if (k == 0) break;
        }
      }
  }
  int u = 0;
  for (int i = 17; i--;)
    if (num[i][n]) u |= f[i];
  q = queue<int>();
  if (!vst[u]) {
    can[u] = 1;
    q.push(u);
  }
  while (!q.empty()) {
    int U = q.front();
    q.pop();
    for (int i = 0, u = U; i < 17; i++, u >>= 1)
      if (u & 1) {
        int v = U ^ f[i];
        if (!vst[v] && !can[v]) {
          can[v] = 1;
          q.push(v);
        }
      }
  }
  int ans = n;
  for (int i = f[18]; i--;)
    if (can[i]) {
      int cnt = 0;
      for (int j = 0, u = i; j < 17; j++, u >>= 1)
        if (u & 1) {
          cnt += num[j][n];
        }
      smin(ans, cnt);
    }
  printf("%d\n", ans);
}
