#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <sstream>
#include <string>
#define repd(i,a,b) for (int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repd(i,0,n)
#define all(x) (x).begin(),(x).end()
#define mod 1000000007
#define inf 2000000007
#define mp make_pair
#define pb push_back
typedef long long ll;
using namespace std;
template <typename T>
inline void output(T a, int p) {
    if(p) cout << fixed << setprecision(p)  << a << "\n";
    else cout << a << "\n";
}
// end of template

// Minimum Cost Flow
struct node {int cost, pos;};
struct edge {int to, cap, cost, rev;};
bool operator < (const node &a, const node &b){
    return a.cost > b.cost;
}

class MinCostFlow {
    
public:
    int V; // ??????????????°
    vector<vector<edge>> G;
    vector<int> h, dist, preV, preE; // ??????????????£?????????????????¢?????´?????????????????´?????????
    
    MinCostFlow(int V) : V(V), G(V), h(V), dist(V), preV(V), preE(V) {}
    
    void add_edge(int from, int to, int cap, int cost) {
        G[from].pb({to, cap, cost, (int)G[to].size()});
        G[to].pb({from, 0, -cost, (int)G[from].size() - 1});
    }
    
    int calc(int s, int t, int f){
        int ret = 0;
        
        h.assign(V, 0);
        while(f > 0) {
            dist.assign(V, inf);
            priority_queue<node> pq;
            pq.push({0, s});
            dist[s] = 0;
            while(!pq.empty()){
                node p = pq.top(); // cost, pos
                pq.pop();
                int d = p.cost;
                int v = p.pos;
                if(dist[v] < d) continue;
                rep(i, G[v].size()){
                    edge &e = G[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]){
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        preV[e.to] = v;
                        preE[e.to] = i;
                        pq.push({dist[e.to], e.to});
                    }
                }
            }
            if(dist[t] == inf) return -1;
            rep(v, V) h[v] += dist[v];
            
            int d = f;
            
            for(int v = t; v != s; v = preV[v]){
                d = min(d, G[preV[v]][preE[v]].cap);
            }
            f -= d;
            ret += d * h[t];
            for(int v = t; v != s; v = preV[v]){
                edge &e = G[preV[v]][preE[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return ret;
    }
    
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);
    // source code
    
    int A, B, K;
    cin >> A >> B >> K;
    MinCostFlow mcf(A + B + 2); // source(1) + A + B + sink(1)
    // 0, (1, 2, ..., A), (A + 1, ..., A + B), A + B + 1
    rep(i, A) mcf.add_edge(0, i + 1, 1, 0);
    rep(i, B) mcf.add_edge(A + i + 1, A + B + 1, 1, 0);
    vector<string> a(A), b(B);
    rep(i, A) cin >> a[i];
    rep(i, B) cin >> b[i];
    rep(i, A) rep(j, B){
        int cost = 0;
        if(a[i][j] == '1') cost++;
        if(b[j][i] == '1') cost++;
        mcf.add_edge(i + 1, A + j + 1, 1, cost);
    }
    
    // ????????¢?´¢
    int l = 0, r = A + B + 1; // ok, ng
    while(r - l > 1){
        int m = (l + r) / 2;
        auto mc = mcf;
        int f = mc.calc(0, A + B + 1, m);
//        cout << m << ", " << f << endl;
        if(f <= K && f != -1) l = m;
        else r = m;
    }
    
    output(l, 0);
    
    
    return 0;
}

Measured memory_bytes: 6064