#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <numeric>
#include <queue>
#include <stack>
#include <map> 
#include <set>
#include <string>
#include <functional>
#include <list>
#include <random>
#include <time.h>
#include <iomanip>
#include <assert.h>
#include <numeric>
#include <new>
#define BIT(nr) (1ULL << (nr))
#define int long long
#define ll long long
#define double long double
#define mod 1000000007
#define MAXN (int)1e+5 * 2+1
#define LL_MAX 9223372036854775807	//ない環境用
#define LL_HALFMAX 9223372036854775807 / 2	//ない環境用
#define MIN -(9223372036854775807 / 2)
#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it)
#define ALLOF(c) (c).begin(), (c).end()
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define mp make_pair
template<typename T1, typename T2> inline void chmin(T1 & a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }


using namespace std;

template <typename T, typename E>
struct SegmentTree {
    typedef function<T(T, T)> F;
    typedef function<T(T, E)> G;
    typedef function<E(E, E)> H;
    typedef function<E(E, int)> P;
    int n;
    F f;
    G g;
    H h;
    P p;
    T d1;
    E d0;
    vector<T> dat;
    vector<E> laz;
    SegmentTree(int n_, F f, G g, H h, T d1, E d0,
        vector<T> v = vector<T>(), P p = [](E a, int b) {return a; }) :
        f(f), g(g), h(h), d1(d1), d0(d0), p(p) {
        init(n_);
        if (n_ == (int)v.size()) build(n_, v);
    }
    //初期化。要素配列と遅延配列を2*n-1個にする
    void init(int n_) {
        n = 1;
        while (n < n_) n *= 2;
        dat.clear();
        dat.resize(2 * n - 1, d1);
        laz.clear();
        laz.resize(2 * n - 1, d0);
    }
    //既存のvectorからセグ木を構築
    void build(int n_, vector<T> v) {
        for (int i = 0; i < n_; i++) dat[i + n - 1] = v[i];
        for (int i = n - 2; i >= 0; i--)
            dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
    }
    //ノードを評価する。
    inline void eval(int len, int k) {
        //遅延配列に単位元が入ってたら評価済みなのでおしまい
        if (laz[k] == d0) return;
        //葉ノードでないなら遅延伝播する
        if (k * 2 + 1 < n * 2 - 1) {
            //h: 2つの作用素を引数に取り合成した作用素を返す関数
            laz[k * 2 + 1] = h(laz[k * 2 + 1], laz[k]);
            laz[k * 2 + 2] = h(laz[k * 2 + 2], laz[k]);
        }
        //p: このノードに対応する区間長と作用素を引数に取り、区間長に対応する作用素を返す関数
        //dat[k] にlaz に溜めていた作用素を適用(g: 要素型と作用素型を引数に取り、要素に作用素を作用させた結果を返す関数、ここでの作用素とは区間Sum区間Addなら (+ 3) とか)
        dat[k] = g(dat[k], p(laz[k], len));
        //適用し終わったので遅延配列をクリア
        laz[k] = d0;
    }
    //[l,r)の区間を再帰的に見ながら0-indexedの[a, b)を更新する
    T update(int a, int b, E x, int k, int l, int r) {
        //先に評価
        eval(r - l, k);
        //範囲外ならなにもしないでそのノードが持つ値を返す
        if (r <= a || b <= l) return dat[k];
        //完全被覆なら既に遅延配列に入っている作用素と追加したい作用素をマージした後にそれを要素に作用させた結果を返す、pは区間長に対応する作用素を得るための（ｒｙ
        if (a <= l && r <= b) {
            laz[k] = h(laz[k], x);
            return g(dat[k], p(laz[k], r - l));
        }
        //完全被覆でも範囲外でもないなら(中途半端にかぶっているなら)完全被覆と範囲外の境界が見えるまで木を潜って変化後の値を得る
        return dat[k] = f(update(a, b, x, k * 2 + 1, l, (l + r) / 2),
            update(a, b, x, k * 2 + 2, (l + r) / 2, r));
    }
    T update(int a, int b, E x) {
        return update(a, b, x, 0, 0, n);
    }

    T update(int a, E x) {
        return update(a, a+1, x, 0, 0, n);
    }

    T query(int a, int b, int k, int l, int r) {
        eval(r - l, k);
        //範囲外なら単位元を返す
        if (r <= a || b <= l) return d1;
        //完全被覆ならそのまま返す
        if (a <= l && r <= b) return dat[k];
        //一部被覆なら完全被覆と範囲外に分かれるまで木を潜る
        T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
        T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
        return f(vl, vr);
    }
    //0-indexedで[a, b)の区間*を求める
    T query(int a, int b) {
        return query(a, b, 0, 0, n);
    }

    T query(int a) {
        return query(a, a+1, 0, 0, n);
    }
};


bool fixed[1000000];

signed main() {
    int N, M;
    string S;
    cin >> N >> M >> S;

    // NG ケース
    int chk = 0;
    int chkCnt = 0;
    rep(i, N + 1) {
        if (S[i] == '0') {
            chmax(chk, chkCnt);
            chkCnt = 0;
        }
        else {
            chkCnt++;
        }
    }

    chmax(chk, chkCnt);

    if (chk >= M) {
        cout << -1 << "\n";
        return 0;
    }

    auto myMin = [](int a, int b) -> int {
        return min(a, b);
    };

    //rmq[i]:= i番目のマスに到達するのに必要な最短手数
    SegmentTree<int, int> rmq(N + 2, myMin, myMin, myMin, LL_HALFMAX, LL_HALFMAX);
    
    rmq.update(0, 0);

    REPS(i, M) {
        if(S[i] == '0') rmq.update(i, 1);
    }

    REP(i, M + 1, N + 1) {
        if (S[i] == '1') {
            continue;
        }

        int rmqRes = rmq.query(i - M, i);
        rmq.update(i, rmqRes + 1);
    }

    vector<int> res;
    rep(i, N + 1) {
        res.push_back(rmq.query(i));
    }

    vector<int> ans;

    int nowPos = N;
    int nxtPos = N;
    int cnt = 0;
    int me = M;
    int procCnt = res[N];

    RREP(i, N + 1) {
        if (cnt > M) {
            cnt = 1;
            ans.push_back(me);
            me = M;
            procCnt--;
            nowPos = nxtPos;
            i = nxtPos - 1;
        }

        //1手前としてありえる
        if (res[i] == procCnt - 1) {
            me = nowPos - i;
            nxtPos = i;
        }

        if (i == 0) {
            ans.push_back(me);
            break;
        }

        cnt++;
    }

    reverse(ALLOF(ans));


    for (int i : ans) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}


Measured memory_bytes: 6772