#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>

#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#define debug(x) cerr << #x << " = " << x << endl;


#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 35

int dp[SIZE][1<<16];

void calc(int n){
  int c;
  int in;
  int a[SIZE] = {} ,b[SIZE] = {};
  
  scanf("%d",&c);

  for(int i=0;i<n;i++){

    for(int j=0;j<16;j++){
      scanf("%d",&in);
      a[i] = a[i]*2 + in;
    }

  }

  for(int i=0;i<c;i++){

    for(int j=0;j<16;j++){
      scanf("%d",&in);
      b[i] = b[i]*2 + in;
    }

  }
  
  for(int i=0;i<=n;i++){
    for(int j=0;j<(1<<16);j++){
      dp[i][j] = -INF;
    }
  }

  dp[0][0] = 0;

  for(int i=0;i<n;i++){
    for(int j=0;j<(1<<16);j++){
      if(dp[i][j] == -INF) continue;
      
      int now = j | a[i];
      
      for(int k=0;k<c;k++){
        int p = __builtin_popcount(now & b[k]);
        
        dp[i+1][now & (~(now & b[k]))] =
          max(dp[i+1][now & (~(now & b[k]))],dp[i][j] + p);        
      }

      dp[i+1][now] = max(dp[i][j],dp[i+1][now]);
    }
  }

  int ans = 0;

  for(int i=0;i<(1<<16);i++){
    ans = max(ans,dp[n][i]);
  }

  printf("%d\n",ans);
}
  

int main(){
  int n;

  while(scanf("%d",&n)!=EOF){
    if(n==0) break;
    calc(n);
  }
  
  return 0;
}