#include <bits/stdc++.h>
using namespace std;
void minimize(int &a, int b) { a = min(a, b); }
const int limit = 100005;
int n, p;
int occurrences[limit][17];
int a[limit];
vector<int> positions[17];
int forbidden[1 << 17];
int curforbidden[1 << 17];
int getset(int i, int j) {
  if (i > j) return 0;
  int c = 0;
  int(&vi)[17] = occurrences[i];
  int(&vj)[17] = occurrences[j];
  for (int b = 0; b < p; b++)
    if (vj[b] > vi[b]) c |= 1 << b;
  return (1 << p) - 1 - c;
}
void computeconj(vector<int> &p) {
  for (int i = 0; i < int(p.size()) - 1; i++)
    curforbidden[getset(p[i], p[i + 1] - 1)] = 1;
}
void computeconj(vector<int> &p0, vector<int> &p1) {
  int i0 = 0;
  int i1 = 0;
  int n0 = int(p0.size());
  int n1 = int(p1.size());
  while (i0 < n0 and i1 < n1) {
    if (p0[i0] < p1[i1] and i0 < n0 - 1 and p0[i0 + 1] < p1[i1])
      i0++;
    else if (p1[i1] < p0[i0] and i1 < n1 - 1 and p1[i1 + 1] < p0[i0])
      i1++;
    else if (p0[i0] < p1[i1]) {
      curforbidden[getset(p0[i0], p1[i1] - 1)] = 1;
      i0++;
    } else {
      curforbidden[getset(p1[i1], p0[i0] - 1)] = 1;
      i1++;
    }
  }
}
void computeconj(int c0, int c1) {
  for (int c = 0; c < 1 << p; c++) curforbidden[c] = 0;
  if (c0 == c1)
    computeconj(positions[c0]);
  else
    computeconj(positions[c0], positions[c1]);
  int C0 = 1 << c0;
  int C1 = 1 << c1;
  for (int c = (1 << p) - 1; c >= 0; c--) {
    if (not curforbidden[c] && (c & C0) && (c & C1)) {
      for (int b = 0; b < p; b++) {
        if (curforbidden[c | (1 << b)]) {
          curforbidden[c] = 1;
          break;
        }
      }
    }
    if (curforbidden[c]) forbidden[c] = 1;
  }
}
void writeconj(int c) {
  for (int b = 0; b < p; b++) cout << ((c & (1 << b)) != 0);
}
int constraint[17][17];
int reachable[1 << 17];
int sol;
int computelen(int c) {
  int len = 0;
  for (int b = 0; b < p; b++)
    if (c & (1 << b)) len += int(positions[b].size());
  return len;
}
int main() {
  ios::sync_with_stdio(false);
  cin >> n >> p;
  string s;
  cin >> s;
  for (int i = 1; i <= n; i++) {
    a[i] = s[i - 1] - 'a';
    for (int b = 0; b < p; b++) occurrences[i][b] = occurrences[i - 1][b];
    occurrences[i][a[i]]++;
    positions[a[i]].push_back(i);
  }
  for (int c0 = 0; c0 < p; c0++)
    for (int c1 = 0; c1 < p; c1++) cin >> constraint[c0][c1];
  for (int c0 = 0; c0 < p; c0++)
    for (int c1 = c0; c1 < p; c1++)
      if (not constraint[c0][c1]) computeconj(c0, c1);
  reachable[(1 << p) - 1] = 1;
  sol = n;
  for (int c = (1 << p) - 2; c >= 0; c--) {
    if (not forbidden[c]) {
      for (int b = 0; b < p; b++) {
        if (reachable[c | (1 << b)]) {
          reachable[c] = 1;
          break;
        }
      }
      if (reachable[c]) {
        minimize(sol, computelen(c));
      }
    }
  }
  cout << sol << endl;
}
