#include<stdio.h>
#define max(x,y) (x<y)?y:x
#define rep(i,n) for(int (i)=0; (i)<(n); (i)++)
int N, M;
char B[514][514];
int E[514];
int dp[2][1<<22];
void mode1(void){
    int ans = 0;
    rep(i,1<<N){
        rep(j,M) E[j]=0;
        int cnt = 0;
        rep(j,N){
            if(i>>j&1){
                cnt++;
                rep(k,M){
                    if(B[j][k]=='1')E[k]=!E[k];
                }
            }
        }
        int flag=1;
        rep(j,M) if(E[j])flag=0;
        if(flag) ans=max(ans,cnt);
    }
    printf("%d\n",ans);
}
void mode2() {
    rep(i, 1 << M)dp[0][i] = -1;
    dp[0][0] = 0;
    int k = 1;
    rep(i, N) {
        int W = 0;
        int d = 1;
        rep(j, M) { //入力を2進数に変換
            W += d * (B[i][M - j - 1] == '1');
            d *= 2;
        }
        rep(j, 1 << M)dp[k][j] = dp[!k][j];
        rep(j, 1 << M) {
            if (dp[!k][j] >= 0) {
                int x = j^W; //101^110=011
                dp[k][x] = max(dp[!k][x], dp[!k][j] + 1);
            }
        }
        //rep(j,1<<M) printf("%2d ",dp[k][j]); puts("");
        k = !k;
    }
    printf("%d\n",dp[!k][0]);
}
int main(void){
    while (1) {
        scanf("%d%d",&N,&M);
        if (N == 0 && M == 0)return 0;
        rep(i, N) scanf("%s",B[i]);
        if (N < M)
            mode1();
        else
            mode2();
    }
    return 0;
}
/*
 wiの排他的論理和をとると0になる
 0 -1 -1 -1 -1 -1  1 -1
 0 -1 -1  2 -1  1  1 -1
 3 -1 -1  2 -1  2  2 -1
 3 -1 -1  3 -1  3  4 -1
 */

