#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  vector<int> fa;
  vector<int> cnt;
  explicit UnionFind(int n) {
    fa.resize(n);
    for (int i = 0; i < n; ++i) fa[i] = i;
    cnt = vector<int>(n, 1);
  }
  int findP(int i) {
    while (i != fa[i]) {
      fa[i] = fa[fa[i]];
      i = fa[i];
    }
    return i;
  }
  int find(int n) {
    int m = n;
    while (fa[m] != m) m = fa[m];
    fa[n] = m;
    return m;
  }
  void unite(int m, int n) {
    int p1 = find(m);
    int p2 = find(n);
    if (p1 != p2) {
      fa[p1] = p2;
      cnt[p2] += cnt[p1];
      cnt[p1] = 0;
    }
    return;
  }
  int g(int son) {
    while (fa[fa[son]] != fa[son]) fa[son] = fa[fa[son]];
    return fa[son];
  }
  void connectAtoB(int a, int b) { unite(a, b); }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n, k;
  cin >> n >> k;
  string s;
  cin >> s;
  vector<vector<int> > mp(n);
  for (int i = 0; i < k; ++i) {
    int c;
    cin >> c;
    for (int j = 0; j < c; ++j) {
      int v;
      cin >> v;
      mp[--v].push_back(i);
      assert(mp[v].size() <= 2);
    }
  }
  UnionFind un(k);
  vector<int> csd(k, -1);
  int res = 0;
  vector<int> bi(k, -1);
  auto choose = [&](int id) {
    int g = un.findP(id);
    assert(csd[g] != 0);
    if (csd[g] == 1) {
      return;
    }
    csd[g] = 1;
    int a = un.cnt[g];
    int b = 0;
    if (bi[g] != -1) {
      csd[un.findP(bi[g])] = 0;
      b = un.cnt[un.findP(bi[g])];
    }
    res -= min(a, b);
    res += a;
  };
  auto unchoose = [&](int id) {
    int g = un.findP(id);
    assert(csd[g] != 1);
    if (csd[g] == 0) {
      return;
    }
    csd[g] = 0;
    int a = un.cnt[g];
    int b = 0;
    if (bi[g] != -1) {
      csd[un.findP(bi[g])] = 1;
      b = un.cnt[un.findP(bi[g])];
    }
    res -= min(a, b);
    res += b;
  };
  auto get = [&](int id) {
    id = un.find(id);
    int a = un.cnt[un.find(id)];
    int b = 0;
    if (bi[id] != -1) b = un.cnt[bi[id]];
    return min(a, b);
  };
  auto unbinda2b = [&](int a, int b) { un.connectAtoB(a, b); };
  auto bindd = [&](int a, int b) {
    a = un.find(a);
    b = un.find(b);
    if (a == b) return;
    if (csd[a] == csd[b] && csd[a] != -1) return;
    if (csd[a] != -1) swap(a, b);
    if (csd[b] != -1) {
      if (csd[b] == 0)
        unchoose(a);
      else
        choose(a);
    } else {
      res -= get(a);
      res -= get(b);
      int ba = bi[a];
      int bb = bi[b];
      un.connectAtoB(a, b);
      if (ba != -1 || bb != -1) {
        if (ba == -1) swap(ba, bb);
        if (bb != -1) {
          un.connectAtoB(bb, ba);
        }
        bi[b] = ba;
        bi[ba] = b;
      }
      res += get(b);
    }
  };
  auto split = [&](int a, int b) {
    a = un.find(a);
    b = un.find(b);
    if (csd[a] != -1 && csd[b] != -1) return;
    if (bi[a] == b) return;
    if (csd[a] != -1) swap(a, b);
    if (csd[b] == -1) {
      res -= get(a);
      res -= get(b);
      if (bi[a] != -1) unbinda2b(bi[a], b);
      if (bi[b] != -1) unbinda2b(bi[b], a);
      a = un.find(a);
      b = un.find(b);
      bi[a] = b;
      bi[b] = a;
      res += get(a);
    } else {
      if (csd[b] == 0) {
        choose(a);
      } else {
        unchoose(a);
      }
    }
  };
  for (int i = 0; i < n; ++i) {
    const vector<int> &candi = mp[i];
    if (candi.size() == 0) {
      cout << res << "\n";
      continue;
    }
    const char si = s[i];
    if (si == '0') {
      if (candi.size() == 1) {
        choose(candi[0]);
      } else {
        split(candi[0], candi[1]);
      }
    } else {
      if (candi.size() == 1) {
        unchoose(candi[0]);
      } else {
        bindd(candi[0], candi[1]);
      }
    }
    cout << res << "\n";
  }
}
