#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 4;
int tree[4 * N];
char S[N];
void build(int cn, int b, int e) {
  if (b == e) {
    tree[cn] = (1 << (S[b] - 'a'));
    return;
  }
  int lc = 2 * cn, rc = lc + 1, mid = (b + e) / 2;
  build(lc, b, mid);
  build(rc, mid + 1, e);
  tree[cn] = tree[lc] | tree[rc];
}
int query(int cn, int b, int e, int i, int j) {
  if (b > j or e < i) return 0;
  if (b >= i and e <= j) return tree[cn];
  int lc = 2 * cn, rc = lc + 1, mid = (b + e) / 2;
  return query(lc, b, mid, i, j) | query(rc, mid + 1, e, i, j);
}
int R[20];
int n, alpha;
const int Mx = 131080;
vector<int> bad[17][17];
bool good[20][20];
bool veryBad[Mx], justBad[Mx];
int Len[Mx];
int freq[20];
int vis[Mx];
int main() {
  cin >> n >> alpha;
  int M = (1 << alpha);
  scanf("%s", S + 1);
  for (int i = 1; i <= n; i++) {
    freq[S[i] - 'a']++;
  }
  for (int i = 0; i < M; i++) {
    Len[i] = n;
    for (int k = 0; k < alpha; k++) {
      if ((i >> k) & 1) Len[i] -= freq[k];
    }
  }
  build(1, 1, n);
  for (int i = 0; i < alpha; i++) {
    for (int j = 0; j < alpha; j++) {
      cin >> good[i][j];
    }
  }
  for (int i = n; i >= 1; i--) {
    int cur = S[i] - 'a';
    for (int j = 0; j < alpha; j++) {
      if (good[cur][j]) continue;
      int nxt = j;
      if (R[nxt] > 0) {
        int jumpTo = R[nxt] - 1;
        int mask = query(1, 1, n, i + 1, jumpTo);
        if (((mask >> cur) & 1) or ((mask >> nxt) & 1)) continue;
        mask |= (1 << cur);
        mask |= (1 << nxt);
        if (cur > nxt) {
          bad[nxt][cur].push_back(mask);
        } else {
          bad[cur][nxt].push_back(mask);
        }
      }
    }
    R[cur] = i;
  }
  for (int i = 0; i < alpha; i++) {
    for (int j = i; j < alpha; j++) {
      for (int k = 0; k < M; k++) justBad[k] = 0;
      queue<int> que;
      for (int mask : bad[i][j]) {
        justBad[mask] = true;
        que.push(mask);
      }
      while (!que.empty()) {
        int u = que.front();
        que.pop();
        int v = ~u & (u + 1);
        if (v == M) continue;
        v = v + u;
        if (justBad[v]) continue;
        justBad[v] = true;
        que.push(v);
      }
      for (int k = 0; k < M; k++) {
        if (!justBad[k]) continue;
        int kk = k ^ (1 << i);
        if (i != j) kk ^= (1 << j);
        veryBad[kk] = true;
      }
    }
  }
  int ans = n;
  queue<int> que;
  que.push(0);
  vis[0] = 1;
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (int k = 0; k < alpha; k++) {
      int v = u | (1 << k);
      if (!veryBad[v] && !vis[v]) {
        vis[v] = 1;
        ans = min(ans, Len[v]);
        que.push(v);
      }
    }
  }
  cout << ans;
}
