#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace __gnu_pbds;   
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> 
#define ll int
#define ld double
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()
#define sz(a) (ll)(a.size())
ll n,p;
const ll M=(1<<17)+10;
bool A[20][20];
bool f[17][17][M];
ll dp[M],pw[22];
std::vector<ll> v[20];
ll solve(ll x)
{
	if(x==0)
		return 0;
	if(dp[x]!=1e7)
		return dp[x];
	dp[x]=0;
	for(ll i=0;i<p;i++)
	{
		if((x&pw[i]))
			dp[x]+=sz(v[i]);
	}
	for(ll i=0;i<p;i++)
	{
		if((x&pw[i])==0)
			continue;
		for(ll j=i;j<p;j++)
			if(f[i][j][x] && (x&pw[j]))
				return 1e7;
	}
	for(ll i=0;i<p;i++)
	{
		if((x&pw[i]))
			dp[x]=min(dp[x],solve(x^pw[i]));
	}
	return dp[x];
}
int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>p;
	string s;
	cin>>s;
	for(ll i=0;i<p;i++)
		for(ll j=0;j<p;j++)
			cin>>A[i][j];
	pw[0]=1;
	for(ll i=1;i<20;i++)
		pw[i]=2*pw[i-1];
	for(ll i=0;i<n;i++)
		v[s[i]-'a'].pb(i);
	for(ll i=0;i<n;i++)
	{
		ll a=s[i]-'a';
		std::vector<pair<ll,ll> > z;
		for(ll j=0;j<p;j++)
		{
			ll x=(ll)(upper_bound(all(v[j]),i)-v[j].begin());
			if(x<sz(v[j]))
				z.pb(mp(v[j][x],j));
		}
		sort(all(z));
		ll T=pw[p]-1;
		for(ll j=0;j<sz(z);j++)
		{
			if(A[a][z[j].ss]==0)
			{
				f[a][z[j].ss][T]=1;
				f[z[j].ss][a][T]=1;
			}
			T=T^pw[z[j].ss];
		}
	}
	for(ll i=0;i<p;i++)
	{
		for(ll j=i;j<p;j++)
		{
			for(ll k=pw[p]-1;k>=0;k--)
			{
				if(f[i][j][k]==0)
					continue;
				for(ll t=0;t<p;t++)
				{
					if((k&pw[t]))
						f[i][j][(k^pw[t])]=1;
				}
			}
		}
	}
	for(ll j=0;j<M;j++)
		dp[j]=1e7;
	cout<<solve(pw[p]-1)<<"\n";
	return 0;
}