#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[100100];
int num[17][100100], A[17][17];
vector<int> pos[17], arr, vec;
int f[17] = {1};
int flag[262144], runs;
int vst[262144], can[262144];
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, c; i <= n; i++) {
    for (int j = p; j--;) num[j][i] = num[j][i - 1];
    c = s[i] - 'a';
    num[c][i]++;
    pos[c].push_back(i);
  }
  for (int i = 1; i < p; i++) f[i] = f[i - 1] << 1;
  int all = (f[p - 1] << 1) - 1;
  for (int i = 0; i < p; i++) {
    for (int j = i; j < p; j++)
      if (!A[i][j]) {
        arr.clear();
        if (i == j) {
          int N = pos[i].size();
          for (int k = 0; k < N; k++) arr.push_back(pos[i][k]);
        } else {
          int iN = pos[i].size(), jN = pos[j].size();
          for (int I = 0, J = 0;;) {
            if (I == iN) {
              if (J == jN) break;
              arr.push_back(pos[j][J++]);
            } else if (J == jN)
              arr.push_back(pos[i][I++]);
            else {
              if (pos[i][I] > pos[j][J])
                arr.push_back(pos[j][J++]);
              else
                arr.push_back(pos[i][I++]);
            }
          }
        }
        vec.clear();
        int N = arr.size(), used = f[i] | f[j], except_all = all ^ used;
        for (int k = 1; k < N; k++) {
          int a = arr[k - 1], b = arr[k], val = 0;
          if (A[s[a] - 'a'][s[b] - 'a']) continue;
          for (int I = p; I--;)
            if (num[I][b - 1] - num[I][a]) val |= f[I];
          vec.push_back(except_all ^ val);
        }
        sort(vec.begin(), vec.end());
        vec.resize(unique(vec.begin(), vec.end()) - vec.begin());
        runs++;
        for (int k = vec.size(); k--;) {
          int bit = vec[k];
          q.push(bit);
          flag[bit] = runs;
        }
        while (!q.empty()) {
          int bit = q.front();
          q.pop();
          vst[bit | used] = 1;
          for (int I = 0, val = bit; I < p; I++, val >>= 1)
            if (val & 1) {
              int nxt_bit = bit ^ f[I];
              if (flag[nxt_bit] != runs) {
                flag[nxt_bit] = runs;
                q.push(nxt_bit);
              }
            }
        }
      }
  }
  int all_bit = 0;
  for (int i = 0; i < p; i++)
    if (num[i][n]) all_bit |= f[i];
  if (!vst[all_bit]) {
    q.push(all_bit);
    can[all_bit] = 1;
  } else
    assert(0);
  int ans = n;
  while (!q.empty()) {
    int bit = q.front(), len = 0;
    q.pop();
    for (int i = 0, val = bit; i < p; i++, val >>= 1)
      if (val & 1) {
        int nxt_bit = bit ^ f[i];
        if (!vst[nxt_bit] && !can[nxt_bit]) {
          can[nxt_bit] = 1;
          q.push(nxt_bit);
        }
        len += num[i][n];
      }
    smin(ans, len);
  }
  printf("%d\n", ans);
}
