#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
const int inf=1e9+7;
const ll longinf=1LL<<60 ;
const ll mod=1e9+7 ;

struct UnionFind{
   vector<int> par;
   UnionFind(int n):par(n,-1){}
   int find(int x){
       if(par[x]<0)return x;
       return par[x]=find(par[x]);
   }
   bool unite(int x,int y){
       x=find(x);
       y=find(y);
       if(x>y)swap(x,y);
       if(x==y)return false;
       else{
           par[x]+=par[y];
           par[y]=x;
       }
       return true;
   }

   bool same(int x,int y){
       return find(x)==find(y);
   }
   int size(int x){
       return -par[find(x)];
   }
};
int main(){
    int h,w;
    cin>>h>>w;
    string s[h];
    rep(i,h)cin>>s[i];
    map<ll,int> dp[h];
    int all=1<<w;
    rep(i,all){
        int a[w];
        rep(j,w){
            if(s[0][j]=='.')a[j]=0;
            if(s[0][j]=='#')a[j]=1;
            if(s[0][j]=='?')a[j]=(i>>j)&1;
        }
        UnionFind uf(w+1);
        bool ok=true;
        rep(j,w-1){
            if(a[j]&&a[j+1])uf.unite(j,j+1);
            if(!a[j]&&!a[j+1])ok=false;
        }
        if(!ok)continue;
        ll res=0;
        int cnt=0;
        rep(j,w){
            res*=12;
            if(a[j])res+=(uf.find(j)+1),cnt++;
        }
        dp[0][res]=max(dp[0][res],cnt);
    }
    rep(i,h-1){
        rep(mask,all){
            int a[w];
            bool can=true;
            rep(j,w){
                if(s[i+1][j]=='.')a[j]=0;
                if(s[i+1][j]=='#')a[j]=1;
                if(s[i+1][j]=='?')a[j]=(mask>>j)&1;
            }
            rep(j,w-1){
                if(!a[j]&&!a[j+1])can=false;
            }
            if(!can)continue;
            for(auto p : dp[i]){
                int b[w];
                ll cur=p.first;
                rep(j,w){
                    b[w-j-1]=12+cur%12;
                    cur/=12;
                }
                bool ok=true;
                UnionFind uf(26);
                rep(j,w-1){
                    if(a[j]&&a[j+1])uf.unite(j,j+1);
                }
                rep(j,w){
                    if(a[j]&&b[j]>12){
                        if(!uf.unite(j,b[j]))ok=false;
                    }
                    if(!a[j]&&b[j]==12)ok=false;
                }
                if(i!=h-2||w!=1)rep(j,w)if(uf.find(b[j])>12)ok=false;
                if(!ok)continue;
                ll res=0;
                int cnt=p.second;
                rep(j,w){
                    res*=12;
                    if(a[j]){
                        res+=(uf.find(j)+1),cnt++;
                    }
                }
                dp[i+1][res]=max(dp[i+1][res],cnt);
            }
        }
    }
    int ans=-1;
    for(auto p : dp[h-1]){
        ll cur=p.first;
        bool ok=true;
        set<int> st;
        while(cur){
            if(cur%12)st.insert(cur%12);
            cur/=12;
        }
        if(st.size()==1||st.size()==0)ans=max(ans,p.second);
    }

    cout<<ans<<endl;
    
    return 0;
}


Measured memory_bytes: 4444