/*
状态dp
n*m的图中 每次选一点 覆盖
。
.
。。+ 。 。
。
。
+不能被。覆盖 问最多能放置几个
m<=10 选/不选 ->状压
dp[i][P][k][L]=max(dp[i][P][k][L],dp[i-1][k][L][F]+sum(P))
第一维不能滚掉 因为 不是紧接着更新的 可能 被这一层已经更新 所以%2 -> 0-n-1
128MB 1e8/8/1024/1024
*/
/*
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e1 +10;
const int mod=998244353;
const int inf=0x3f3f3f3f;
int n,m,dp[3][(1<<10)+10][(1<<10)+10],sum[(1<<10)+10],a[110],ans;
int getsum(int k)
{
int res=0;
while(k)
{
if(k&1) res++;
k>>=1;
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
char tmp;cin>>tmp;
a[i]<<=1,a[i]+=(tmp=='H');
}
}
//for(int i=1;i<=n;i++) cout<<a[i]<<endl;
for(int i=0;i<(1<<m);i++) sum[i]=getsum(i);
for(int S=0;S<(1<<m);S++){
if((a[0]&S || S&(S<<2) || S&(S<<1))==0)
dp[0][S][0]=getsum(S);
}
for(int S=0;S<(1<<m);S++){
for(int L=0;L<(1<<m);L++){
if((L&a[0] || S&a[1] || S&L || L&(L<<1) || L&(L<<2) || S&(S<<1) || S&(S<<2) )==0 )
dp[1][S][L]=sum[S]+sum[L];//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for(int i=2;i<n;i++)
{
for(int S=0;S<(1<<m);S++)
{
if(S&(S<<1) || S&(S<<2) || S&a[i]) continue;
for(int L=0;L<(1<<m);L++)
{
if(L&(L<<1) || L&(L<<2) || L&a[i-1] || L&S ) continue;
for(int FL=0;FL<(1<<m);FL++)
{
if(FL&(FL<<1) || FL&(FL<<2) || FL&a[i-2] || FL&S || FL&L) continue;
dp[i%2][S][L]=max(dp[i%2][S][L],dp[(i-1)%2][L][FL]+sum[S]);
}
}
}
}
for(int L=0;L<(1<<m);L++)//!!!!!!!!!!!!!!!!!!!!!!!!!!
for(int S=0;S<(1<<m);S++)
ans=max(ans,dp[(n-1)%2][S][L]);
cout<<ans<<'\n';
return 0;
}