#include <bits/stdc++.h>
const long maxn = 22;
const long inf2 = 100;
char a[maxn][maxn];
char b[maxn][maxn];
long n, m, resx, resy, choicex, choicey, q, k, cht;
bool good;
bool canr(long mnx1, long mny1, long mnx2, long mny2) {
  long x, y;
  bool pp = false;
  for (x = mnx1; x <= mnx1 + choicex - 1; x++) {
    for (y = mny1; y <= mny1 + choicey - 1; y++)
      if (b[x][y] != b[mnx2 + x - mnx1][mny2 + y - mny1]) {
        pp = true;
        break;
      }
    if (pp == true) break;
  }
  if (pp == false) return (false);
  pp = false;
  for (x = mnx1; x <= mnx1 + choicex - 1; x++) {
    for (y = mny1; y <= mny1 + choicey - 1; y++)
      if (b[x][y] !=
          b[mnx2 + choicex - 1 - (x - mnx1)][mny2 + choicey - 1 - (y - mny1)]) {
        pp = true;
        break;
      }
    if (pp == true) break;
  }
  return (pp);
}
void change(long mnx1, long mny1) {
  long x, y;
  long nowy = mny1 + choicey - 1;
  long nowx = mnx1 + choicex - 1;
  for (x = 0; x <= choicex - 1; x++)
    for (y = choicey - 1; y >= 0; y--) {
      b[nowx][nowy] = a[x + mnx1][y + mny1];
      nowx--;
      if (nowx < mnx1) {
        nowy--;
        nowx = mnx1 + choicex - 1;
      }
    }
}
bool cans(long mnx1, long mny1, long mnx2, long mny2) {
  bool first = canr(mnx1, mny1, mnx2, mny2);
  change(mnx1, mny1);
  bool second = canr(mnx1, mny1, mnx2, mny2);
  return (first && second);
}
void make_copy() {
  for (long q = 1; q <= n; q++)
    for (long j = 1; j <= m; j++) b[q][j] = a[q][j];
}
void check() {
  long amx = n / choicex;
  long amy = m / choicey;
  bool now;
  long mnx1, mny1, mnx2, mny2;
  for (mnx1 = 0; mnx1 <= amx - 1; mnx1++)
    for (mny1 = 0; mny1 <= amy - 1; mny1++)
      for (mnx2 = mnx1; mnx2 <= amx - 1; mnx2++)
        for (mny2 = 0; mny2 <= amy - 1; mny2++)
          if ((mnx2 > mnx1) || ((mnx2 == mnx1) && (mny2 > mny1))) {
            make_copy();
            if (choicex != choicey)
              now = canr(mnx1 * choicex + 1, mny1 * choicey + 1,
                         mnx2 * choicex + 1, mny2 * choicey + 1);
            else
              now = cans(mnx1 * choicex + 1, mny1 * choicey + 1,
                         mnx2 * choicex + 1, mny2 * choicey + 1);
            if (now == false) {
              good = false;
              return;
            }
          }
}
int main() {
  scanf("%ld%ld\n", &n, &m);
  for (q = 1; q <= n; q++) {
    for (k = 1; k <= m; k++) a[q][k] = getchar();
    scanf("\n");
  }
  resx = inf2;
  resy = inf2;
  cht = 0;
  for (choicex = 1; choicex <= n; choicex++)
    if (n % choicex == 0)
      for (choicey = 1; choicey <= m; choicey++)
        if (m % choicey == 0) {
          good = true;
          check();
          if (good == true) {
            cht++;
            if ((choicex * choicey < resx * resy) ||
                ((choicex * choicey == resx * resy) && (choicex < resx))) {
              resx = choicex;
              resy = choicey;
            }
          }
        }
  printf("%ld\n%ld %ld", cht, resx, resy);
}
