#include <bits/stdc++.h>
using namespace std;
inline void setmin(int &x, int y) {
  if (y < x) x = y;
}
inline void setmax(int &x, int y) {
  if (y > x) x = y;
}
inline void setmin(long long &x, long long y) {
  if (y < x) x = y;
}
inline void setmax(long long &x, long long y) {
  if (y > x) x = y;
}
const int N = 100000;
const int inf = (int)1e9 + 1;
const long long big = (long long)1e18 + 1;
const int P = 239;
const int P1 = 31;
const int P2 = 57;
const int MOD = (int)1e9 + 7;
const int MOD1 = (int)1e9 + 9;
const int MOD2 = 998244353;
const double eps = 1e-9;
const double pi = atan2(0, -1);
const int ABC = 26;
vector<int> g[N];
vector<int> gr[N];
vector<int> order;
bool used[N];
void dfs(int u) {
  used[u] = true;
  for (int v : g[u]) {
    if (!used[v]) {
      dfs(v);
    }
  }
  order.push_back(u);
}
int col[N];
void dfs1(int u, int c) {
  col[u] = c;
  used[u] = true;
  for (int v : gr[u]) {
    if (!used[v]) {
      dfs1(v, c);
    }
  }
}
vector<pair<int, int> > G[N];
vector<int> comp[N];
vector<int> g0[N];
int COL[N];
int PER[N];
int ttt = 0;
int USED[N];
bool try_col(int u, int cnt) {
  USED[u] = ttt;
  for (int v : g0[u]) {
    if (USED[v] != ttt) {
      COL[v] = (COL[u] < cnt - 1 ? COL[u] + 1 : 0);
      if (!try_col(v, cnt)) {
        return false;
      }
    } else {
      if (COL[v] != (COL[u] < cnt - 1 ? COL[u] + 1 : 0)) {
        return false;
      }
    }
  }
  return true;
}
int GCD(int x, int y) {
  while (x) {
    y %= x;
    swap(x, y);
  }
  return y;
}
string a[N];
int cnt[N][50];
int dp[N][50];
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m, k;
  cin >> n >> m >> k;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    g[u].push_back(v);
    gr[v].push_back(u);
  }
  fill(used, used + n, false);
  for (int i = 0; i < n; i++) {
    if (!used[i]) {
      dfs(i);
    }
  }
  reverse(order.begin(), order.end());
  int C = 0;
  fill(used, used + n, false);
  for (int i : order) {
    if (!used[i]) {
      dfs1(i, C++);
    }
  }
  for (int i = 0; i < n; i++) {
    comp[col[i]].push_back(i);
  }
  for (int i = 0; i < n; i++) {
    for (int j : g[i]) {
      if (col[i] != col[j]) {
        G[col[i]].push_back({i, j});
      }
    }
  }
  for (int i = 0; i < C; i++) {
    sort(G[i].begin(), G[i].end());
    G[i].resize(unique(G[i].begin(), G[i].end()) - G[i].begin());
  }
  for (int id = 0; id < C; id++) {
    for (int i : comp[id]) {
      for (int j : g[i]) {
        if (col[j] == id) {
          g0[i].push_back(j);
        }
      }
    }
    int sz = comp[id].size();
    int gcd = -1;
    for (int i = k; i >= 1; i--) {
      if (k % i != 0) {
        continue;
      }
      ttt++;
      COL[comp[id][0]] = 0;
      if (try_col(comp[id][0], i)) {
        gcd = i;
        break;
      }
    }
    assert(gcd != -1);
    gcd = GCD(gcd, k);
    PER[id] = gcd;
    ttt++;
    COL[comp[id][0]] = 0;
    assert(try_col(comp[id][0], gcd));
  }
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  for (int id = 0; id < C; id++) {
    for (int d = 0; d < PER[id]; d++) {
      for (int u : comp[id]) {
        bool ok = false;
        for (int t = 0; t < k / PER[id]; t++) {
          if (a[u][(d + COL[u] + t * PER[id]) % k] == '1') {
            ok = true;
            break;
          }
        }
        if (ok) {
          cnt[id][d]++;
        }
      }
    }
  }
  for (int id = C - 1; id >= 0; id--) {
    for (int d = 0; d < k; d++) {
      for (auto it : G[id]) {
        int u = it.first, v = it.second;
        int TTT = d + COL[u];
        if (TTT >= k) {
          TTT -= k;
        }
        for (int t = 0; t < k / PER[id]; t++) {
          if (t > 0) {
            TTT += PER[id];
            if (TTT >= k) {
              TTT -= k;
            }
          }
          setmax(dp[id][d], dp[col[v]][(TTT + 1 - COL[v] + k) % k]);
        }
      }
      dp[id][d] += cnt[id][d % PER[id]];
    }
  }
  cout << dp[col[0]][COL[0]] << "\n";
  return 0;
}
