#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
#include<utility>
#include<string>
#include<cmath>
#include <numeric>
#include<map>
#include<cstdio>
 
 
#define REP(i, n) for(int i = 0;i < n;i++)
#define REPR(i, n) for(int i = n;i >= 0;i--)
#define FOR(i, m, n) for(int i = m;i < n;i++)
#define FORR(i, m, n) for(int i = m;i >= n;i--)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define llong long long
#define pb(a) push_back(a)
#define INF 1e13
using namespace std;
typedef pair<int, int> P;
typedef pair<llong, llong> LP;
typedef pair<int, P> PP;
typedef pair<llong, LP> LPP;
 
typedef long long int ll;
#define MOD 1000000007
#define MAX_H 101
#define MAX_W 101

int h,w;
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,1,-1};
char tmp[3] = {'@','#','*'};

char mp[MAX_H][MAX_W];


void dfs(int x,int y,int k){

     //今いるところをHに置き換える
    mp[x][y] = 'H';
    //移動方向をループ
    for(int i = 0;i <= 4;i++){
        //for(int dy = -1;dy <= 1;dy++){
            //x方向にdx,ｙ方向にdy移動した場所を(nx,ny)とする
            int nx = x + dx[i], ny = y + dy[i];
            //nx,nyが庭の範囲内にあるか、また、現在の場所field[nx][ny]が@か#か*かの判定
            if(0 <= nx && nx < h && 0 <= ny && ny < w && mp[nx][ny] == tmp[k]){
                dfs(nx,ny,k);
            }
         //}
     }
     return;
}




void solve(){

    int res = 0;
    REP(k,3){
        for(int i = 0;i < h;i++){
            for(int j = 0;j < w;j++){
                if(mp[i][j] == tmp[k]){
                    //@や#、*が残っているならばその場所からdfsを始める
                    dfs(i,j,k);
                    //ここで1つの島が見つかったことになるので水たまりの個数を１つ足す
                    res++;
                }
            }
        }
    }
    //島の個数を表示
    cout << res << endl;
}


int main(){

    while(cin >> h >> w,h){

        REP(i,h){
            REP(j,w){
                cin >> mp[i][j];
            }
        }
        solve();
    }
    return 0;
}

