Problem:
Property Distribution

タナカ氏が HW アールの果樹園を残して亡くなりました。果樹園は東西南北方向に H × W の区画に分けられ、区画ごとにリンゴ、カキ、ミカンが植えられています。タナカ氏はこんな遺言を残していました。

果樹園は区画単位でできるだけ多くの血縁者に分けること。ただし、ある区画の東西南北どれかの方向にとなりあう区画に同じ種類の果物が植えられていた場合は、区画の境界が分からないのでそれらは 1 つの大きな区画として扱うこと。

例えば次のような 3 × 10 の区画であれば ('リ'はリンゴ、'カ'はカキ、'ミ'はミカンを表す)

同じ樹がある区画の間の境界を消すと次のようになり、

結局 10 個の区画、つまり 10 人で分けられることになります。

雪が降って区画の境界が見えなくなる前に分配を終えなくてはなりません。あなたの仕事は果樹園の地図をもとに分配する区画の数を決めることです。

果樹園の地図を読み込み、分配を受けられる血縁者の人数を出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットは空白で区切られた H, W (H, W ≤ 100) を含む行から始まり、続いて H × W の文字からなる H 行の文字列が与えられます。この文字列には、リンゴを表す '@'、カキを表す '#'、ミカンを表す '*'、の 3 文字しか現れません。

入力はゼロが２つの行で終わります。データセットの数は 20 を超えません。

Output

各データセットごとに、分配を受ける人数を１行に出力してください。

Sample Input

10 10
####*****@
@#@@@@#*#*
@##***@@@*
#****#*@**
##@*#@@*##
*@@@@*@@@#
***#@*@##*
*@@@*@@##@
*@*#*@##**
@****#@@#@
0 0

Output for the Sample Input

33

Solution in JAVA (judge verdict: Accepted)

import java.io.*;
import java.util.*;

public class Main{
	public static void main(String args[]){
		try{
			new Main();
		}catch(IOException err){
			err.printStackTrace();
		}
	}
	
	int[][] offset = new int[][]{
			{-1, 0}, {1, 0}, {0, -1}, {0, 1}
	};


	public Main() throws IOException, StackOverflowError{
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		List<Integer> Ans = new ArrayList<Integer>();
		String line;

		while((line = in.readLine()) != null){
			String[] dst = line.split(" ");
			int h = Integer.parseInt(dst[0]);
			int w = Integer.parseInt(dst[1]);

			if(h==0 && w==0){
				break;
			}

			int[][] data = new int[h+2][w+2];
			int[][] label = new int[h+2][w+2];
			for(int j=1; j<=h; j++){
				line = in.readLine();
				for(int i=1; i<=w; i++){
					String c = line.substring(i-1, i);
					if(c.equals("@")){
						data[j][i] = 1;
					}
					else if(c.equals("#")){
						data[j][i] = 2;
					}
					else if(c.equals("*")){
						data[j][i] = 3;
					}
					label[j][i] = 0;
				}
			}
			
			for(int j=0; j<h+2; j++){
				data[j][0] = 0;
				data[j][w+1] = 0;
				label[j][0] = -1;
				label[j][w+1] = -1;
			}
			
			for(int i=0; i<w+2; i++){
				data[0][i] = 0;
				data[h+1][i] = 0;
				label[0][i] = -1;
				label[h+1][i] = -1;
			}
			

			int count = 0;
			for(int j=1; j<=h; j++){
				for(int i=1; i<=w; i++){
					if(label[j][i] == 0){
						count++;
						label[j][i] = count;
						grouping(data, label, i, j);
					}
				}
			}

			Ans.add(count);
		}

		for(int n=0; n<Ans.size(); n++){
			System.out.println(Ans.get(n));
		}
	}

	public void grouping(int[][] data, int[][] label, int x, int y){
		List<point> cue = new ArrayList<point>();
		cue.add(new point(x, y));
		while(cue.size() != 0){
			point p = cue.get(0);
			cue.remove(0);
			for(int d=0; d<4; d++){
				int xx = p.x + offset[d][0];
				int yy = p.y + offset[d][1];
				if(label[yy][xx] == 0 && data[yy][xx] == data[p.y][p.x]){
					label[yy][xx] = label[p.y][p.x];
					cue.add(new point(xx, yy));
				}
			}
		}
	}
}

class point{
	int x;
	int y;
	
	public point(int x, int y){
		this.x = x;
		this.y = y;
	}
}