#include <bits/stdc++.h>
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wunused-macros"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wsign-compare"
using namespace std;
static bool debug = false;
template <typename T, typename Q, typename S>
bool Bounded(const T &x, const Q &a, const S &b) {
  return a <= x && x <= b;
}
template <typename T>
int sz(const T &x) {
  return x.size();
}
template <typename T, typename Q>
bool mem(const T &s, const Q &x) {
  return s.find(x) != s.end();
}
template <typename T>
void push(vector<T> &c, const T &e) {
  c.push_back(e);
}
template <typename T>
void push(queue<T> &c, const T &e) {
  c.push(e);
}
template <typename T>
void push(set<T> &c, const T &e) {
  c.insert(e);
}
template <typename T, typename... Args>
auto emplace(vector<T> &c, Args &&...args)
    -> decltype(c.emplace_back(args...)) {
  c.emplace_back(args...);
}
template <typename T, typename... Args>
auto emplace(queue<T> &c, Args &&...args) -> decltype(c.emplace(args...)) {
  c.emplace(args...);
}
template <typename T, typename... Args>
auto emplace(set<T> &c, Args &&...args) -> decltype(c.emplace(args...)) {
  c.emplace(args...);
}
template <typename T>
void umin(T &x, const T &y) {
  x = min(x, y);
}
template <typename T>
void umax(T &x, const T &y) {
  x = max(x, y);
}
template <typename T>
int sign(const T &x) {
  return x == 0 ? 0 : x > 0 ? 1 : -1;
}
template <typename T>
T square(const T &x) {
  return x * x;
}
template <typename S, typename T>
istream &operator>>(istream &in, pair<S, T> &p) {
  return in >> p.first >> p.second;
}
template <typename T, typename I = typename T::iterator>
void read(T &cnt) {
  for (auto &x : cnt) cin >> x;
}
template <typename S, typename T>
ostream &operator<<(ostream &out, const pair<S, T> &p) {
  return out << "{" << p.first << ", " << p.second << "}";
}
template <typename T>
struct show_container {
  const T &container;
  show_container(const T &container_) : container(container_) {}
};
template <typename T>
ostream &operator<<(ostream &o, const show_container<T> &thing) {
  bool first = true;
  o << "{";
  for (const auto &x : thing.container) {
    if (!first) o << ", ";
    first = false;
    o << x;
  }
  o << "}";
  return o;
}
template <typename T>
show_container<T> show(const T &container) {
  return show_container<T>(container);
}
struct dout_ {
} dout;
template <typename T>
dout_ &operator<<(dout_ &out, const T &thing) {
  if (debug) cout << thing;
  return out;
}
dout_ &operator<<(dout_ &out, ostream &(*thing)(ostream &)) {
  if (debug) cout << thing;
  return out;
}
struct outboth {
  ostream &a;
  ostream &b;
  outboth(ostream &a_, ostream &b_) : a(a_), b(b_) {}
};
template <typename T>
outboth &operator<<(outboth &both, const T &thing) {
  both.a << thing;
  both.b << thing;
  return both;
}
outboth &operator<<(outboth &both, ostream &(*thing)(ostream &)) {
  both.a << thing;
  both.b << thing;
  return both;
}
struct ScopeTiming_impl {
  string filename, function;
  int lineno;
  string label;
  int *counter;
  chrono::time_point<std::chrono::high_resolution_clock> startTime, endTime;
  ScopeTiming_impl(string filename_ = "<no file>", string function_ = "<>",
                   int lineno_ = -1, string label = "", int *counter_ = nullptr)
      : filename(filename_),
        function(function_),
        lineno(lineno_),
        label(label),
        counter(counter_) {
    startTime = std::chrono::high_resolution_clock::now();
  }
  ~ScopeTiming_impl() {
    if (!debug) return;
    endTime = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = endTime - startTime;
    cout << filename << ":" << lineno << ":" << function;
    if (!label.empty()) cout << ":" << label;
    if (counter) cout << "[" << ++*counter << "]";
    cout << ": Time taken: ";
    int oldprec = cout.precision(3);
    auto oldflags = cout.setf(std::ios::fixed);
    cout << (1e3 * elapsed.count()) << "ms." << endl;
    cout.flags(oldflags);
    cout.precision(oldprec);
  }
};
struct UF {
  vector<size_t> rep, rank;
  UF(size_t n) : rep(n), rank(n) {
    for (size_t i = 0; i < n; ++i) rep[i] = i, rank[i] = 1;
  }
  size_t lookup(size_t a) {
    size_t u = a, v = rep[u], r;
    while (u != v) u = v, v = rep[u];
    r = u;
    for (u = a, v = rep[u]; v != r; u = v, v = rep[u]) rep[u] = r;
    return r;
  }
  void merge(size_t a, size_t b) {
    size_t u = lookup(a), v = lookup(b);
    if (u == v) return;
    if (rank[u] > rank[v])
      rep[v] = rep[u], rank[u] += rank[v];
    else
      rep[u] = rep[v], rank[v] += rank[u];
  }
};
void solve(ostream &rout) {
  std::ios::sync_with_stdio(false);
  cin.tie(nullptr);
  const array<int, 4> DI = {{0, -1, 0, 1}}, DJ = {{1, 0, -1, 0}};
  int N, K;
  while (cin >> N >> K, cin.good()) {
    vector<string> S(N);
    read(S);
    UF uf(N * N);
    auto okay = [&](int i, int j) {
      return Bounded(i, 0, N - 1) && Bounded(j, 0, N - 1);
    };
    auto blocked = [&](int i, int j) { return S[i][j] == 'X'; };
    for (int i = 0; i < int(N); ++i)
      for (int j = 0; j < int(N); ++j)
        for (int d = 0; d < int(4); ++d) {
          if (blocked(i, j)) continue;
          int k = i + DI[d], l = j + DJ[d];
          if (!okay(k, l) || blocked(k, l)) continue;
          uf.merge(i * N + j, k * N + l);
        }
    vector<vector<int>> adjacent(N * N);
    for (int i = 0; i < int(N); ++i)
      for (int j = 0; j < int(N); ++j) adjacent[N * i + j].reserve(4);
    for (int i = 0; i < int(N); ++i)
      for (int j = 0; j < int(N); ++j) {
        if (blocked(i, j)) continue;
        int u = N * i + j, p = uf.lookup(u);
        adjacent[u].push_back(p);
        for (int d = 0; d < int(4); ++d) {
          int k = i + DI[d], l = j + DJ[d];
          if (okay(k, l) && blocked(k, l)) adjacent[k * N + l].push_back(p);
        }
      }
    for (auto &p : adjacent) {
      sort(p.begin(), p.end());
      p.erase(unique(p.begin(), p.end()), p.end());
    }
    int best = -1;
    vector<int> seen(N * N);
    int total = 0, numBlocked = 0;
    auto decrement = [&](int i, int j) {
      assert(Bounded(i, 0, N - 1) && Bounded(j, 0, N - 1));
      numBlocked -= blocked(i, j);
      for (auto p : adjacent[N * i + j]) {
        assert(seen[p] >= 1);
        seen[p]--;
        if (seen[p] == 0) total -= uf.rank[p];
      }
    };
    auto increment = [&](int i, int j) {
      assert(Bounded(i, 0, N - 1) && Bounded(j, 0, N - 1));
      numBlocked += blocked(i, j);
      for (auto p : adjacent[N * i + j]) {
        seen[p]++;
        if (seen[p] == 1) total += uf.rank[p];
      }
    };
    for (int i = 0; i < int(K - 1); ++i)
      for (int j = 0; j < int(K); ++j) increment(i, j);
    for (int i = 0; i + K <= N; ++i) {
      int jFirst, jLast, jIncr;
      if (i % 2 == 0)
        jFirst = 0, jLast = N - K, jIncr = +1;
      else
        jFirst = N - 1, jLast = K - 1, jIncr = -1;
      for (int j = jFirst; j != jFirst + K * jIncr; j += jIncr)
        increment(i + K - 1, j);
      for (int j = jFirst; j != jLast + jIncr; j += jIncr) {
        if (j != jFirst) {
          for (int k = i; k < i + K; ++k) {
            decrement(k, j - jIncr);
            increment(k, j + (K - 1) * jIncr);
          }
        }
        umax(best, numBlocked + total);
      }
      for (int j = jLast; j != jLast + K * jIncr; j += jIncr) decrement(i, j);
    }
    rout << best << endl;
  }
}
int main() {
  solve(cout);
  return 0;
}
