#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <sstream>
#include <vector>
using namespace std;

#define REP2(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define FOREACH(i, c) for(auto i = (c).begin(); i != (c).end(); ++i)
#define BIT(n, m) (((n) >> (m)) & 1)

typedef long long ll;
typedef pair<int, int> PI;

const ll inf = 1e15;
const ll mod = 1000 * 1000 * 1000 + 7;
const double eps = 1e-9;

template <typename S, typename T> ostream &operator<<(ostream &out, const pair<S, T> &p) {
  out << "(" << p.first << ", " << p.second << ")";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  REP(i, v.size()){
    if (i > 0) out << ", ";
    out << v[i];
  }
  out << "]";
  return out;
}

class BipartiteMatching{
  int V;
  int W;
  vector<int> match;
  vector<int> level;
  vector<vector<int> > graph;
  
  int bfs(){
    fill(level.begin(), level.end(), -1);
    queue<int> que;
    for(int v = 0; v < V; v++){
      if(match[v] == -1){
        que.push(v);
        level[v] = 0;
      }
    }
    bool done = true;
    while(!que.empty()){
      int v = que.front(); que.pop();
      for(size_t i = 0; i < graph[v].size(); i++){
        int w = graph[v][i], nextv = match[w];
        if(nextv == -1){
          done = false;
        }else if(level[nextv] == -1){
          level[nextv] = level[v] + 1;
          que.push(nextv);
        }
      }
    }
    return !done;
  }
  
  bool dfs(int v){
    for(size_t i = 0; i < graph[v].size(); i++){
      int w = graph[v][i], nextv = match[w];
      if(nextv == -1 || (level[nextv] == level[v] + 1 && dfs(nextv))){
        match[v] = w;
        match[w] = v;
        return true;
      }
    }
    level[v] = -2;
    return false;
  }

public:
  BipartiteMatching(int _V, int _W) :
    V(_V), W(_W),
    match(vector<int>(V + W, -1)),
    level(vector<int>(V)),
    graph(vector<vector<int> >(V)){}
  
  void add_edge(int from, int to){
    assert(0 <= from && from < V && 0 <= to && to < W);
    graph[from].push_back(V + to);
  }
  
  int solve(){
    int ans = 0;
    while(bfs()){
      for(int v = 0; v < V; v++){
        if(match[v] == -1 && dfs(v)) ans++;
      }
    }
    return ans;
  }
};

int main(){
  int H, W;
  while (cin >> H >> W && H){
    vector<string> B(H + 2, string(W + 2, '.'));
    REP(i, H) REP(j, W) cin >> B[i + 1][j + 1];
    vector<pair<PI, PI> > U;
    vector<pair<PI, PI> > V;

    int res = 1;
    REP2(i, 1, H) REP2(j, 1, W){
      int count = 0;
      REP(k, 4){
        int ni = i + k % 2;
        int nj = j + k / 2;
        if (B[ni][nj] == '#') count++;
      }

      if (count != 3) continue;
      res++;

      int di[] = {0, 0, 1, 1, 0, 0, 1};
      int dj[] = {0, 1, 1, 0, 0, 1, 1};
      REP(k, 4){
        int ni1 = i + di[k], ni2 = i + di[k + 1];
        int nj1 = j + dj[k], nj2 = j + dj[k + 1];
        if (B[ni1][nj1] != B[ni2][nj2]){
          int dh[] = {1,  0, -1, 0};
          int dw[] = {0,- 1,  0, 1};
          PI p(i, j);
          PI q(i, j);
          while (B[q.first + di[k + 2]][q.second + dj[k + 2]] == '#' &&
                 B[q.first + di[k + 3]][q.second + dj[k + 3]] == '#'){
            q.first  += dh[k];
            q.second += dw[k];
          }

          if (B[q.first + di[k + 2]][q.second + dj[k + 2]] == '#' ||
              B[q.first + di[k + 3]][q.second + dj[k + 3]] == '#'){
            assert(p != q);
            pair<PI, PI> L = p <= q ? make_pair(p, q) : make_pair(q, p);
            if (p.first == q.first) U.push_back(L);
            else V.push_back(L);
          }
        }
      }
    }
    sort(ALL(U));
    U.erase(unique(ALL(U)), U.end());
    sort(ALL(V));
    V.erase(unique(ALL(V)), V.end());
    // cout << res << endl;
    // cout << U << endl << V << endl;
    
    
    BipartiteMatching bm(U.size(), V.size());
    REP(i, U.size()) REP(j, V.size()) {
      if (V[j].first.first  <= U[i].first.first  && U[i].first.first  <= V[j].second.first &&
          U[i].first.second <= V[j].first.second && V[j].first.second <= U[i].second.second)
        bm.add_edge(i, j);
    }
    cout << res - (U.size() + V.size() - bm.solve()) << endl;
  }
  return 0;
}

Measured memory_bytes: 1600