#include using namespace std; #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define repr(i, n) for (int i = (int)(n); i >= 0; i--) #define all(v) v.begin(), v.end() #define mod1 1000000007 #define mod2 998244353 typedef long long ll; int main(){ ll H,W; cin >> H >> W; vector S(H); rep(i,H){ cin >> S[i]; } ll len = H + W - 2; vector>> dp(len / 2 + 1, vector>(H, vector(H, 0))); if (S[0][0] == S[H - 1][W - 1]){ dp[0][0][0] = 1; } else{ dp[0][0][0] = 0; } for (ll i = 0; i < len / 2; i++){ //i + 1: 進んだ文字の数.j: 縦.(i + 1 - j):横.H - 1 - k: 縦. for (ll j = 0; j <= i; j++){ for (ll k = 0; k <= i; k++){ if (j < H && i + 1 - j < W && H - 1 - k >= 0 && W - 2 - i + k >= 0){//横,横 if (S[j][i + 1 - j] == S[H - 1 - k][W - 1 - (i + 1 - k)]){ dp[i + 1][j][k] = (dp[i + 1][j][k] + dp[i][j][k]) % mod1; } } if (j < H && i + 1 - j < W && H - 1 - k - 1 >= 0 && W - 1 - (i + 1 - k - 1) >= 0){//横,縦 if (S[j][i + 1 - j] == S[H - 1 - k - 1][W - 1 - i + k]){ dp[i + 1][j][k + 1] = (dp[i + 1][j][k + 1] + dp[i][j][k]) % mod1; } } if (j + 1 < H && i - j < W && H - 1 - k >= 0 && W - 1 - (i + 1 - k) >= 0){//縦,横 if (S[j + 1][i - j] == S[H - 1 - k][W - 1 - (i + 1 - k)]){ dp[i + 1][j + 1][k] = (dp[i + 1][j + 1][k] + dp[i][j][k]) % mod1; } } if (j + 1 < H && i - j < W && H - 1 - k - 1 >= 0 && W - 1 - (i + 1 - k - 1) >= 0){//縦,縦 if (S[j + 1][i - j] == S[H - 1 - k - 1][W - 1 - (i + 1 - k - 1)]){ dp[i + 1][j + 1][k + 1] = (dp[i + 1][j + 1][k + 1] + dp[i][j][k]) % mod1; } } } } } /*for (ll i = 0; i <= len / 2; i++){ for (ll j = 0; j < H; j++){ for (ll k = 0; k < H; k++){ cout << dp[i][j][k] << " "; } cout << endl; } }*/ ll ans = 0; if (len % 2 == 0){ for (ll j = 0; j < H; j++){ for (ll k = 0; k < H; k++){ if (j + k == H - 1) ans = (ans + dp[len / 2][j][k]) % mod1; } } } else{ for (ll j = 0; j < H; j++){ for (ll k = 0; k < H; k++){ if (j + k == H - 1 || j + k == H - 2) ans = (ans + dp[len / 2][j][k]) % mod1; } } } cout << ans << endl; }