import std.stdio;
import std.format;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

int popcnt(int x) {
    int Ret = 0;
    foreach (i; 0 .. 16) {
        if (x & (1 << i)) Ret++;
    }
    return Ret;
}

int popCount[1 << 16];
static this() {
    foreach (i; 0 .. (1 << 16)) {
        popCount[i] = popcnt(i);
    }
}

void main() {
    int N, C;
    int[] A, B;
    bool input() {
        scanf("%d %d\n", &N, &C);
        if (N == 0 && C == 0) return false;
        A = new int[N];
        B = new int[C];
        foreach (i; 0 .. N) {
            int bit;
            foreach (j, x; readln.chomp.split(" ").map!(to!int).array) {
                bit |= (x << j);
            }
            A[i] = bit;
        }
        foreach (i; 0 .. C) {
            int bit;
            foreach (j, x; readln.chomp.split(" ").map!(to!int).array) {
                bit |= (x << j);
            }
            B[i] = bit;
        }
        return true;
    }
    void solve() {
        static int dp[2][1<<16];
        memset(dp.ptr, -1, dp.sizeof);
        dp[0][0] = 0;
        foreach (i; 0 .. N) {
            dp[(i + 1) & 1][] = -1;
            foreach (j; 0 .. (1 << 16)) {
                if (dp[i & 1][j] == -1) continue;
                int bit = j | A[i];
                foreach (b; B) {
                    dp[(i + 1) & 1][bit & ~b] = max(dp[(i + 1) & 1][bit & ~b], dp[i & 1][j] + popCount[bit & b]);
                }
            }
        }
        writeln(dp[N & 1].reduce!max);
    }
    while (input) solve;
}