#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;

char field[100][100];
bool visited[100][100];
int W, H;

int tx[] = {1, 0, -1, 0};
int ty[] = {0, -1, 0, 1};
struct Tree {
  int lx, rx;
  int block[15];
  vector<Tree> child;
  Tree () {
      fill(block, block + 15, 0);
  }
  Tree(int rx, int ry, vector<Tree> child) : lx(lx), rx(rx), child(child) {
    fill(block, block + 15, 0);
  }
  void print() {
    printf("lx, rx = %d, %d\n", lx, rx);
    for (int i = 0; i < child.size(); i++) {
      child[i].print();
    }
  }

  int num(int idx) {
    int n = 0;
    for (int i = 0; i < child.size(); i++) {
      n += child[i].num(idx);
    }
    n += block[idx];
    return n;
  }

  int numChild() {
    int n = 0;
    for (int i = 0; i < child.size(); i++) {
      n += child[i].numChild();
    }
    return n + 1;
  }
};

typedef pair<int, int> P;
typedef pair<Tree, bool> Res;

void init() {
  fill(&field[0][0], &field[99][100], '!');
  fill(&visited[0][0], &visited[99][100], false);
}

Res search(char c, int cx, int cy, bool isBottom) {
  //printf("called\n");
  //printf("%c, %d, %d\n", c, cx, cy);
  queue<P> Q;
  Q.push(P(cx, cy));
  Tree t;
  vector<P> next;
  t.lx = cx, t.rx = cx;
  bool p = false;
  while (!Q.empty()) {
    P cur = Q.front();
    Q.pop();
    int x = cur.first;
    int y = cur.second;
    
    if (visited[y][x] || field[y][x] != c) {
      continue;
    }
    p = true;
    //printf("%d %d\n", x, y);
    visited[y][x] = true;
    t.block[x]++;

    if (field[y - 1][x] != '.' && field[y - 1][x] != '!' && field[y - 1][x] != c) {
      next.push_back(P(x, y - 1));
      //printf("%d, %d\n", x, y - 1);
    }

    if (!isBottom && field[y + 1][x] != '.' && field[y + 1][x] != '!' && field[y + 1][x] != c) {
      t.lx = min(t.lx, x);
      t.rx = max(t.rx, x);
    }

    if (isBottom && field[y + 1][x] == '!') {
      t.lx = min(t.lx, x);
      t.rx = max(t.rx, x);
    }

    for (int i = 0; i < 4; i++) {
      int nx = x + tx[i];
      int ny = y + ty[i];
      if (field[ny][nx] == c && !visited[ny][nx]) {
        Q.push(P(nx, ny));
      }
    }
  }
  if (!p) {
    return Res(Tree(), false);
  }
  for (int i = 0; i < next.size(); i++) {
    int x = next[i].first;
    int y = next[i].second;
    Res res = search(field[y][x], x, y, false);
    if (res.second) {
      t.child.push_back(res.first);
    }
  }
  return Res(t, true);
}

Tree make_tree() {
  for (int i = H; i >= 1; i--) {
    for (int j = 1; j <= W; j++) {
      if (field[i][j] != '.') {
        char c = field[i][j];
        Res r = search(c, j, i, true);
        Tree t = r.first;
        return t;
      }
    }
  }
}

bool check(Tree t) {
  if (t.child.size() == 0) {
    double g = 0.0;
    for (int i = 1; i <= W; i++) {
      g += t.block[i] * (i - 0.5);
    }
    g /= 4;
    // printf("g = %lf\n", g);
    if (t.lx - 1 < g && g < t.rx) {
      return true;
    } else {
      return false;
    }
  }

  for (int i = 0; i < t.child.size(); i++) {
    if (!check(t.child[i])) {
      return false;
    }
  }
  
  double g = 0;
  for (int i = 1; i <= W; i++) {
    g += (i - 0.5) * t.num(i);
  }
  g /= (4 * (t.numChild()));
  //printf("G = %lf\n", g);
  if (t.lx - 1 < g && g < t.rx) {
    return true;
  } else {
    return false;
  }
}

void solve() {
  Tree t = make_tree();
  //t.print();

  if (check(t)) {
    printf("STABLE\n");
  } else {
    printf("UNSTABLE\n");
  }
}

int main() {
  while (true) {
    scanf("%d %d ", &W, &H);
    init();
    if (W == 0 && H == 0) {
      return 0;
    }
    for (int i = 1; i <= H; i++) {
      for (int j = 1; j <= W; j++) {
        scanf("%c ", &field[i][j]);
      }
    }
    solve();
  }
}

Measured memory_bytes: 0