#include <bits/stdc++.h>
using namespace std;
inline long long mod(long long n, long long m) {
  long long ret = n % m;
  if (ret < 0) ret += m;
  return ret;
}
long long gcd(long long a, long long b) {
  return (b == 0LL ? a : gcd(b, a % b));
}
long long exp(long long a, long long b, long long m) {
  if (b == 0LL) return 1LL;
  if (b == 1LL) return mod(a, m);
  long long k = mod(exp(a, b / 2, m), m);
  if (b & 1LL) {
    return mod(a * mod(k * k, m), m);
  } else
    return mod(k * k, m);
}
long long n, p;
const long long N = 100100;
char s[N];
const long long P = 17;
long long a[P][P];
bool ruim[P][P][(1 << P) + 10];
vector<long long> pos[P];
long long pre[N][P];
void calc(long long c1, long long c2) {
  long long A = c1, B = c2;
  long long i = 0, j = 0;
  while (i < (long long)pos[c1].size() and j < (long long)pos[c2].size()) {
    if (i == j and c1 == c2) {
      i++;
      continue;
    }
    long long msk = 0;
    if (pos[c1][i] >= pos[c2][j]) {
      swap(c1, c2);
      swap(i, j);
    }
    for (long long k = 0; k < (p); ++k) {
      if ((pre[pos[c2][j] - 1][k] - pre[pos[c1][i]][k]) > 0) msk |= (1 << k);
    }
    i++;
    if (msk & (1 << c1)) continue;
    if (msk & (1 << c2)) continue;
    ruim[A][B][msk ^ ((1 << p) - 1)] = 1;
  }
  c1 = A, c2 = B;
  for (long long msk = (1 << p) - 1; msk > 0; msk--) {
    if (!ruim[A][B][msk]) continue;
    for (long long k = 0; k < (p); ++k)
      if ((msk & (1 << k)) and k != c1 and k != c2) {
        ruim[A][B][msk ^ (1 << k)] = 1;
      }
  }
}
long long cnt[N];
long long dp[(1 << P) + 10];
long long go(long long msk) {
  if (dp[msk] != -1) return dp[msk];
  if (__builtin_popcount(msk) == 1) {
    return dp[msk] = 0;
  }
  long long res = 0;
  for (long long j = 0; j < (p); ++j)
    if (msk & (1 << j)) res += cnt[j];
  for (long long j = 0; j < (p); ++j)
    if (msk & (1 << j)) {
      long long nmsk = (1 << j) ^ msk;
      bool good = 1;
      for (long long i = 0; i < (p); ++i) {
        if (nmsk & (1 << i)) {
          for (long long k = 0; k < (p); ++k) {
            if (nmsk & (1 << k)) {
              if (ruim[i][k][nmsk]) {
                good = 0;
                break;
              }
            }
          }
        }
      }
      if (good) {
        res = min(res, go(nmsk));
      }
    }
  return dp[msk] = res;
}
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  memset(dp, -1, sizeof(dp));
  cin >> n >> p;
  for (long long i = 1; i <= n; i++) {
    cin >> s[i], cnt[s[i] - 'a']++;
    for (long long j = 0; j < (p); ++j) pre[i][j] = pre[i - 1][j];
    pre[i][s[i] - 'a']++;
    pos[s[i] - 'a'].push_back(i);
  }
  for (long long i = 0; i < p; i++) {
    for (long long j = 0; j < p; j++) {
      cin >> a[i][j];
      if (a[i][j] == 1) {
      } else {
        calc(i, j);
      }
    }
  }
  long long full = 0;
  for (long long j = 0; j < (p); ++j)
    if (cnt[j]) full |= (1 << j);
  cout << go(full) << "\n";
}
