#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

#ifdef __has_include
#if __has_include(<boost / version.hpp>)
#include <boost/range.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm_ext.hpp>
using namespace boost;
using namespace boost::adaptors;
#endif
#endif

auto init_ = [] {
    std::ios_base::sync_with_stdio(false);
    std::cout << std::fixed;
    return 0;
}();

template <typename T>
inline T in()
{
    T x;
    std::cin >> x;
    return x;
}

template <typename T, typename U = std::vector<T>>
inline U in(int n)
{
    U v(n);
    for (int i = 0; i < n; ++i)
    {
        std::cin >> v[i];
    }
    return v;
}

template <typename T, typename U = std::vector<T>, typename V = std::vector<U>>
inline V in(int h, int w)
{
    V vv(h, U(w));
    for (int i = 0; i < h; ++i)
    {
        for (int j = 0; j < w; ++j)
        {
            std::cin >> vv[i][j];
        }
    }
    return vv;
}

template <typename T>
inline void out(const T &x)
{
    std::cout << x << std::endl;
}

template <char delimiter = ' ', typename T, typename... Ts>
inline void out(const T &t, const Ts &... ts)
{
    std::cout << t << delimiter;
    out(ts...);
}

template <char delimiter = ' ', typename T>
inline void vout(const T &v, int n)
{
    for (int i = 0; i < n; ++i)
    {
        if (i)
            std::cout << delimiter;
        std::cout << v[i];
    }
    std::cout << std::endl;
}

int a[301][301][301];

int memo[301][301][301];

int h, w;

int dfs(int i, int j, int k)
{
    if (memo[i][j][k] != -1)
    {
        return memo[i][j][k];
    }

    auto ret = 1 << 29;

    if (j == h && k == h)
    {
        return 0;
    }

    if (j != h)
    {
        ret = min(ret, dfs(i, j + 1, k) + a[i][j][k]);
    }

    if (k != h)
    {
        ret = min(ret, dfs(i, j, k + 1) + a[i][j][k]);
    }

    return memo[i][j][k] = ret;
}

int main()
{
    h = in<int>();
    w = in<int>();

    auto d = in<string>(h);
    vector<vector<int>> c(w, vector<int>(h));

    for (int i = 0; i < h; ++i)
    {
        for (int j = 0; j < w; ++j)
        {
            c[j][i] = d[i][j];
        }
    }

    fill((int *)memo, (int *)(memo + 301), -1);

    for (int k = 0; k < w - 1; ++k)
    {
        for(int i = 0; i < h; ++i) {
            int cnt = 0;
            for(int j = 0; j < h - i; ++j) {
                if(c[k][j] == c[k + 1][j + i]) {
                    cnt++;
                }
            }
            a[k][i][0] = cnt;
        }

        for(int i = 0; i < h; ++i) {
            int cnt = 0;
            for(int j = 0; j < h - i; ++j) {
                if(c[k][j + i] == c[k + 1][j]) {
                    cnt++;
                }
            }
            a[k][0][i] = cnt;
        }

        for(int i = 1; i < h; ++i) {
            for(int j = 1; j < h; ++j) {
                a[k][i][j] = a[k][i - 1][j - 1] - (c[k][h - i] == c[k + 1][h - j]); 
            }
        }
    }

    int sum = 0;
    for(int i = 0; i < w - 1; ++i) {
        sum += dfs(i, 0, 0);
    }

    out(sum);
}

Measured memory_bytes: 213120