#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int n, p;
char s[maxn];
int mat[18][18];
struct node {
  int msk;
  int a;
  node(int aa, int bb) { a = aa, msk = bb; }
};
bool vis[18][1 << 18];
bool dead[1 << 18];
void work(int x) {
  memset(vis, 0, sizeof(vis));
  queue<node> que;
  int lastp = -1;
  int cntmsk = 0;
  for (int i = 0; i < n; i++) {
    int id = s[i] - 'a';
    if (lastp != -1 && mat[x][id] == 0 && !(cntmsk >> id & 1)) {
      if (vis[id][cntmsk] == 0) {
        vis[id][cntmsk] = 1;
        que.push(node(id, cntmsk));
      }
    }
    cntmsk |= (1 << id);
    if (id == x) {
      lastp = i;
      cntmsk = 0;
    }
  }
  lastp = -1;
  for (int i = n - 1; i >= 0; i--) {
    int id = s[i] - 'a';
    if (lastp != -1 && mat[x][id] == 0 && !(cntmsk >> id & 1)) {
      if (vis[id][cntmsk] == 0) {
        vis[id][cntmsk] = 1;
        que.push(node(id, cntmsk));
      }
    }
    cntmsk |= (1 << id);
    if (id == x) {
      lastp = i;
      cntmsk = 0;
    }
  }
  while (!que.empty()) {
    node cnt = que.front();
    que.pop();
    dead[cnt.msk] = 1;
    for (int i = 0; i < p; i++) {
      if (i == x || i == cnt.a) continue;
      int newmsk = cnt.msk | (1 << i);
      if (vis[cnt.a][newmsk]) continue;
      vis[cnt.a][newmsk] = 1;
      que.push(node(cnt.a, newmsk));
    }
  }
}
int cou[maxn];
int ans;
bool vis1[1 << 18];
void dfs(int cntmsk, int cnt = n) {
  ans = min(ans, cnt);
  vis1[cntmsk] = 1;
  for (int i = 0; i < p; i++) {
    if (dead[cntmsk | (1 << i)]) continue;
    if (vis1[cntmsk | (1 << i)]) continue;
    dfs(cntmsk | (1 << i), cnt - cou[i]);
  }
}
int main() {
  scanf("%d%d", &n, &p);
  scanf("%s", s);
  for (int i = 0; i < p; i++) {
    for (int j = 0; j < p; j++) {
      scanf("%d", &mat[i][j]);
    }
  }
  for (int i = 0; i < p; i++) {
    work(i);
  }
  for (int i = 0; i < n; i++) {
    cou[s[i] - 'a']++;
  }
  ans = n;
  dfs(0);
  printf("%d\n", ans);
  return 0;
}
