#include<bits/stdc++.h> 
#define rg register 
#define fp( i , x , y ) for( rg int i=(x); i<=(y); ++i ) 
#define fq( i , x , y ) for( rg int i=(y); i>=(x); --i ) 
#define i60 long long 
#define dou double 
using namespace std ; 
const int N = 1e5+10 , M = 20 , S = (1<<17) ;  
string st ; 
int n , m , len , lis[M] , cnt[M] , a[M][M] , f[S] ; 
bool vis[M][M][S] , se[S] ; 
int calc( int nw ) { 
  int tot = 0 ; 
  fp( i , 1 , m ) if( nw & (1<<i-1) ) tot += cnt[i] ;  
  return n - tot/2 ; 
} 
void add( int nw ) { 
  int p = -1 ; cnt[nw] ++ ; 
  fp( j , 1 , len ) if( lis[j] == nw ) { p = j ; break ; } 
  if( p == -1 ) { 
    fq( j , 1 , len ) lis[j+1] = lis[j] ; len ++ ; lis[1] = nw ;  
  } else { 
	fq( j , 1 , p-1 ) lis[j+1] = lis[j] ; lis[1] = nw ;   
  } 
} 
void ranse( int k1 , int k2 , int nw ) { 
  if( vis[k1][k2][nw] ) return ;
  vis[k1][k2][nw] = 1 ; se[nw] = 1 ; 
  fp( i , 1 , m ) 
    if( i != k1 && i != k2 && ( nw&(1<<i-1) ) == 0 ) 
	 ranse( k1 , k2 , (nw|(1<<i-1)) ) ;  
} 
void work( int st ) { 
  int nw = 0 ; 
  fp( i , 1 , len-1 ) { 
    if( nw & (1<<st-1) ) break ;  nw |= (1<<lis[i]-1) ; 
    if( a[st][lis[i+1]] ) continue ; 	
    if( (nw&(1<<st-1) == 0) && (nw&(1<<lis[i+1]-1) == 0) ) 
      ranse( st , lis[i+1] , nw ) ; 
  } 
} 
signed main( ) { 
  ios::sync_with_stdio(false) ; 
  cin.tie(0) ; 
  cin >> n >> m >> st ; 
  fp( i , 1 , m ) fp( j , 1 , m ) cin >> a[i][j] ; 
  len = 0 ; fp( i , 1 , n )  work( st[i-1]-'a'+1 ) , add( st[i-1]-'a'+1 ) ;  
  len = 0 ; fq( i , 1 , n )  work( st[i-1]-'a'+1 ) , add( st[i-1]-'a'+1 ) ; 
  memset( f , -1 , sizeof(f) ) ; f[0] = 1 ; 
  int ans = n ; 
  fp( i , 0 , (1<<m)-1 ) { 
    if( f[i] == -1 ) continue ; 
    fp( j , 1 , m ) { 
      if( (1<<j-1) & i ) continue ; if( se[i|(1<<j-1)] ) continue ; 
      f[i|(1<<j-1)] = 1 ; 
	} 
    ans = min( ans , calc(i) ) ;  
  } 
  cout << ans << '\n' ; 
  return 0 ; 
}  