import java.util.*

fun main(args:Array<String>?): Unit {
    while(true){
        val (w, h) = readLine()!!.trim().split(' ').map(String::toInt)
        if (w == 0 && h == 0) return
        val state = Array(h){ readLine()!!.trim()}
        println(if(solve(state)) "STABLE" else "UNSTABLE")
    }
}
typealias Block = Stack<Pair<Int, Int>>
fun solve(state: Array<String>): Boolean {
    val h = state.size
    val w = state.first().length
    val union = UnionFind(h * w)
    val moment = IntArray(h * w){0}
    val blocks = Array(h * w){Block()}
    val upperBlock = Array(h * w){Stack<Pair<Int, IntRange>>()}
    for (i in 0 until h) for (j in 0 until w) if (state[i][j] != '.') {
        if (i + 1 < h && state[i + 1][j] == state[i][j]) union.merge(i * w + j, i * w + j + w)
        if (j + 1 < w && state[i][j + 1] == state[i][j]) union.merge(i * w + j, i * w + j + 1)
    }
    for (i in 0 until h) for (j in 0 until w) if (state[i][j] != '.') {
        blocks[union.findRoot(i * w + j)].add(Pair(i, j))
        moment[union.findRoot(i * w + j)] += j * 2 + 1
    }
    for (u in 0 until union.size) if (union.sizeOf(u) == 4){
        blocks[u]
                .filter{(i, j) ->
                    i - 1 >= 0 && state[i - 1][j] != '.' && state[i][j] != state[i - 1][j]
                }
                .map{(i, j) ->
                    union.findRoot(i * w + j - w)
                }.distinct()
                .forEach { v ->
                    blocks[v].filter{(i, j) -> i + 1 < h && union.findRoot((i + 1) * w + j) == u}.map(Pair<*, Int>::second).let{
                        upperBlock[u].push(Pair(v, it.min()!! .. it.max()!!))
                    }
                }
    }
    fun sub(current: Int): Int? {
        if (upperBlock[current].isEmpty()) return moment[current]
        for ((upper, range) in upperBlock[current]) {
            val upperMoment = sub(upper) ?: return null
            val size = union.sizeOf(upper)
            if (size * 2 * range.first < upperMoment && upperMoment < size * 2 * (range.last + 1)) {
                moment[current] += upperMoment
                union.merge(current, upper)
            }else return null
        }
        return moment[current]
    }
    return (0 until w).filter{j -> state.last()[j] != '.'}.let{it.min()!! .. it.max()!!}.let{range ->
        val block = union.findRoot((h - 1) * w + range.first)
        sub(block)?.takeIf{upperMoment ->
            val size = union.sizeOf(block)
            size * 2 * range.first < upperMoment && upperMoment < size * 2 * (range.last + 1)
        } != null
    }
}
class UnionFind(val size: Int){
    private val mArray = IntArray(size){-1}
    fun merge(a: Int, b: Int): Unit {
        val ar = findRoot(a)
        val br = findRoot(b)
        if (ar != br){
            if (mArray[ar] < mArray[br]){
                mArray[ar] += mArray[br]
                mArray[br] = ar
            }else {
                mArray[br] += mArray[ar]
                mArray[ar] = br
            }
        }
    }
    fun findRoot(a: Int): Int {
        return if (mArray[a] >= 0){
            mArray[a] = findRoot(mArray[a])
            mArray[a]
        }else {
            a
        }
    }
    fun sizeOf(a: Int): Int {
        return -mArray[findRoot(a)]
    }
    fun isSame(a: Int, b: Int): Boolean {
        return findRoot(a) == findRoot(b)
    }
}


Measured memory_bytes: 43824