#include <bits/stdc++.h>
using namespace std;
const int P = 17;
int n, p, scnt[P];
string s;
bool A[P][P];
bool bad[1 << P][P][P], badCombined[1 << P], visited[1 << P];
void printMask(int v) {
  for (int i = 0; i < (int)p; i++) cout << ((v >> i) & 1);
  cout << endl;
}
void markBadDfs(int v, int l, int r) {
  if (bad[v][l][r]) return;
  bad[v][l][r] = true;
  for (int i = 0; i < (int)p; i++)
    if (i != l && i != r)
      if (v & (1 << i)) {
        markBadDfs(v ^ (1 << i), l, r);
      }
}
int search(int v) {
  if (visited[v] || badCombined[v]) return n;
  visited[v] = true;
  int best = 0;
  for (int i = 0; i < (int)p; i++)
    if (v & (1 << i)) {
      best += scnt[i];
    }
  for (int i = 0; i < (int)p; i++)
    if (v & (1 << i)) {
      best = min(best, search(v ^ (1 << i)));
    }
  return best;
}
int main() {
  cin >> n >> p >> s;
  for (int i = 0; i < (int)p; i++)
    for (int j = 0; j < (int)p; j++) cin >> A[i][j];
  for (int i = 0; i < (int)p; i++)
    for (int j = 0; j < (int)i + 1; j++)
      if (!A[i][j]) {
        vector<int> pos;
        for (int k = 0; k < (int)n; k++)
          if (s[k] - 'a' == i || s[k] - 'a' == j) {
            pos.push_back(k);
          }
        for (int k = 0; k < (int)pos.size(); k++) {
          if (!k) continue;
          if (s[pos[k]] == s[pos[k - 1]] && i != j) continue;
          int mask = (1 << p) - 1;
          for (int z = pos[k - 1] + 1; z < pos[k]; z++)
            mask &= ~(1 << (s[z] - 'a'));
          markBadDfs(mask, i, j);
        }
      }
  for (int i = 0; i < (int)1 << p; i++) {
    for (int l = 0; l < (int)p; l++)
      for (int r = 0; r < (int)p; r++) {
        badCombined[i] |= bad[i][l][r];
      }
  }
  int initMask = 0;
  for (int i = 0; i < (int)n; i++) {
    initMask |= 1 << (s[i] - 'a');
    scnt[s[i] - 'a']++;
  }
  cout << search(initMask) << endl;
  return 0;
}
