Problem:
JOI 紋章(JOI Emblem)
情報オリンピック日本委員会では，台湾大会に向かう選手を応援するために新しいJOI 旗を作成することにした．
JOI 旗は，正方形が縦に $M$ 行，横に $N$ 列並んだ形をしており，各正方形には J，O，I のいずれかの文字が1 つずつ書かれている．
情報オリンピック日本委員会はJOI 旗とは別にJOI 紋章というものを決めている．JOI 紋章は，正方形が縦に2 行，横に2 列並んだ形をしており，各正方形にはJ，O，I のいずれかの文字が1 つずつ書かれている．
JOI 旗に含まれるJOI 紋章の個数とは，JOI 旗に含まれる縦2 行，横2 列の領域のうち，その領域のJ，O，I の配置がJOI 紋章と(回転や裏返しをせずに) 一致しているものの個数のことである．条件を満たす縦2 行，横2 列の領域同士が重なっていてもそれらを別々に数えるものとする．
情報オリンピック日本委員会は古いJOI 旗と1 枚の白紙を持っている．白紙はJOI 旗を構成する正方形1 個分の大きさで，J，O，I のうち好きな1 文字を書き込むことができる．情報オリンピック日本委員会は以下のいずれか1 つの操作をして，新しいJOI 旗を作成することにした．
古いJOI 旗に対して何も操作せず，そのまま新しいJOI 旗とする．白紙は使用しない．
白紙に1 文字書き込み，古いJOI 旗のいずれかの正方形に重ねて貼り付けることで古いJOI 旗のうち1 箇所を変更する．変更後のJOI 旗を新しいJOI 旗とする．
情報オリンピック日本委員会は新しいJOI 旗に含まれるJOI 紋章の個数をできるだけ多くしたいと思っている．あなたは新しいJOI 旗に含まれるJOI 紋章の個数の最大値を求めることになった．
課題
古いJOI 旗とJOI 紋章の情報が与えられたとき，新しいJOI 旗に含まれるJOI 紋章の個数の最大値を求めるプログラムを作成せよ．
入力
標準入力から以下のデータを読み込め．
1 行目には2 個の整数 $M, N$ が空白を区切りとして書かれている．これはJOI 旗が正方形が縦に$M$行，横に$N$ 列並んだ形であることを表している．
続く$M$ 行の各行には，それぞれ$N$ 文字からなる文字列が書かれている．各文字はJ，O，I のいずれかであり，$M$ 行のうち上から$i$ 行目$(1 \leq i \leq M)$ に書かれている文字列の左から$j$ 文字目$(1 \leq j \leq N)$は古いJOI 旗の上から$i$ 行目，左から$j$ 列目の正方形に書かれている文字を表す．
続く2 行の各行には，それぞれ2 文字からなる文字列が書かれている．各文字はJ，O，I のいずれかであり，2 行のうち上から$i$ 行目$(1 \leq i \leq 2)$ に書かれている文字列の左から$j$ 文字目$(1 \leq j \leq 2)$ はJOI 紋章の上から$i$ 行目，左から$j$ 列目の正方形に書かれている文字を表す．
出力
標準出力に，新しいJOI 旗に含まれるJOI 紋章の個数の最大値を表す整数を1 行で出力せよ．
制約
すべての入力データは以下の条件を満たす．
$2 \leq M \leq 1000$
$2 \leq N \leq 1000$
入出力例
入力例 1
3 5
JOIJO
IJOOO
IIJIJ
JO
IJ
出力例 1
3
古いJOI 旗とJOI 紋章は問題文中の例の通りである．上から2 行目，左から4 列目の正方形を白紙を用いてJ に変更すると，次のような形になる．
このように変更した後のJOI 旗には次に示す3 箇所にJOI 紋章と同じ配置の領域がある．
JOI 紋章と同じ配置の領域が4 箇所以上となる新しいJOI 旗は存在しないので，新しいJOI 旗に含まれるJOI 紋章の個数の最大値は3 である．
入力例 2
2 6
JOJOJO
OJOJOJ
OJ
JO
出力例 2
2
白紙を使用しなくても最大値が得られる場合があることに注意せよ．
入力例 3
2 2
JI
IJ
JJ
JJ
出力例 3
0
この入出力例の場合，考えられるどの新しいJOI 旗においても，JOI 紋章が1 つも含まれない．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string S[1000],U[1000], T[2]; int H, W, cnt, maxn; char F[4] = "JOI";
int main() {
	cin >> H >> W;
	for (int i = 0; i < H; i++) { cin >> S[i]; U[i] = S[i]; }
	for (int i = 0; i < 2; i++) cin >> T[i];
	for (int i = 0; i < H - 1; i++) {
		for (int j = 0; j < W - 1; j++) {
			if (S[i][j] == T[0][0] && S[i][j + 1] == T[0][1] && S[i + 1][j] == T[1][0] && S[i + 1][j + 1] == T[1][1])cnt++;
		}
	}
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			for (int k = 0; k < 3; k++) {
				S[i][j] = F[k]; int sum = 0;
				for (int l = max(0, i - 1); l <= min(H - 2, i); l++) {
					for (int m = max(0, j - 1); m <= min(W - 2, j); m++) {
						if (S[l][m] == T[0][0] && S[l][m + 1] == T[0][1] && S[l + 1][m] == T[1][0] && S[l + 1][m + 1] == T[1][1])sum++;
					}
				}
				for (int l = max(0, i - 1); l <= min(H - 2, i); l++) {
					for (int m = max(0, j - 1); m <= min(W - 2, j); m++) {
						if (U[l][m] == T[0][0] && U[l][m + 1] == T[0][1] && U[l + 1][m] == T[1][0] && U[l + 1][m + 1] == T[1][1])sum--;
					}
				}
				maxn = max(maxn, sum);
				S[i][j] = U[i][j];
			}
		}
	}
	cout << cnt + maxn << endl;
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 6392
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)

int main(){
    int m,n;
    cin >> m >> n;
    vector<vector<char>> hata(m,vector<char>(n));
    rep(i,m){
        rep(j,n){
            cin >> hata[i][j];
        }
    }
    vector<vector<char>> mon(2,vector<char>(2));
    rep(i,2){
        rep(j,2){
            cin >> mon[i][j];
        }
    }
    int cur=0;
    rep(i,m-1){
        rep(j,n-1){
            if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
            hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                cur++;
            }
        }
    }
    vector<char> s={'J','O','I'};
    int ans=cur;
    rep(i,m){
        rep(j,n){
            int now=hata[i][j];
            rep(k,3){
                int res=cur;
                if(i==0 && j==0){
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res--;
                    }
                }
                else if(i==m-1 && j==0){
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res--;
                    }
                }
                else if(i==0 && j==n-1){
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res--;
                    }
                }
                else if(i==m-1 && j==n-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res--;
                    }                    
                }
                else if(i==0){
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res--;
                    }                    
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res--;
                    }
                }
                else if(i==m-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res--;
                    }
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res--;
                    }                    
                }
                else if(j==0){
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res--;
                    }
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res--;
                    }
                }
                else if(j==n-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res--;
                    }
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res--;
                    }                                        
                }
                else{
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res--;
                    }
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res--;
                    }
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res--;
                    }                    
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res--;
                    }
                }
                hata[i][j]=s[k];
                if(i==0 && j==0){
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res++;
                    }
                }
                else if(i==m-1 && j==0){
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res++;
                    }
                }
                else if(i==0 && j==n-1){
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res++;
                    }
                }
                else if(i==m-1 && j==n-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res++;
                    }                    
                }
                else if(i==0){
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res++;
                    }                    
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res++;
                    }
                }
                else if(i==m-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res++;
                    }
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res++;
                    }                    
                }
                else if(j==0){
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res++;
                    }
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res++;
                    }
                }
                else if(j==n-1){
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res++;
                    }
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res++;
                    }                                        
                }
                else{
                    if(hata[i-1][j-1]==mon[0][0] && hata[i-1][j]==mon[0][1] &&
                    hata[i][j-1]==mon[1][0] && hata[i][j]==mon[1][1]){
                        res++;
                    }
                    if(hata[i-1][j]==mon[0][0] && hata[i-1][j+1]==mon[0][1] &&
                    hata[i][j]==mon[1][0] && hata[i][j+1]==mon[1][1]){
                        res++;
                    }
                    if(hata[i][j-1]==mon[0][0] && hata[i][j]==mon[0][1] &&
                    hata[i+1][j-1]==mon[1][0] && hata[i+1][j]==mon[1][1]){
                        res++;
                    }                    
                    if(hata[i][j]==mon[0][0] && hata[i][j+1]==mon[0][1] &&
                    hata[i+1][j]==mon[1][0] && hata[i+1][j+1]==mon[1][1]){
                        res++;
                    }
                }
                hata[i][j]=now;
                ans=max(ans,res);
            }
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4492
final_rank: 11

code_snippet: #include <stdio.h>
#include <algorithm>
#include <string>
using namespace std;

int main() {
    int H, W;
    scanf("%d %d", &H, &W);

    // マップの動的配列を作成
    char** map = new char*[H];
    for (int i = 0; i < H; i++) map[i] = new char[W + 1];

    // マップの入力
    for (int i = 0; i < H; i++) scanf("%s", map[i]);

    char emblem[2][3];
    scanf("%s", emblem[0]);
    scanf("%s", emblem[1]);

    int base = 0;

    // ベースとなるパターンのカウント
    for (int row = 0; row < H - 1; row++) {
        for (int col = 0; col < W - 1; col++) {
            if (map[row][col] == emblem[0][0] && map[row][col + 1] == emblem[0][1] &&
                map[row + 1][col] == emblem[1][0] && map[row + 1][col + 1] == emblem[1][1]) {
                base++;
            }
        }
    }

    int max_add = 0;
    char pre_char, array[4] = "JOI";

    // 各マップの位置に対して、文字を変更して最大の追加パターンを計算
    for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
            pre_char = map[row][col];

            int pre_num = 0;

            // 現在のパターン数をカウント
            if (row - 1 >= 0 && col - 1 >= 0) {
                if (map[row - 1][col - 1] == emblem[0][0] && map[row - 1][col] == emblem[0][1] &&
                    map[row][col - 1] == emblem[1][0] && map[row][col] == emblem[1][1]) pre_num++;
            }
            if (row - 1 >= 0 && col + 1 <= W - 1) {
                if (map[row - 1][col] == emblem[0][0] && map[row - 1][col + 1] == emblem[0][1] &&
                    map[row][col] == emblem[1][0] && map[row][col + 1] == emblem[1][1]) pre_num++;
            }
            if (row + 1 <= H - 1 && col - 1 >= 0) {
                if (map[row][col - 1] == emblem[0][0] && map[row][col] == emblem[0][1] &&
                    map[row + 1][col - 1] == emblem[1][0] && map[row + 1][col] == emblem[1][1]) pre_num++;
            }
            if (row + 1 <= H - 1 && col + 1 <= W - 1) {
                if (map[row][col] == emblem[0][0] && map[row][col + 1] == emblem[0][1] &&
                    map[row + 1][col] == emblem[1][0] && map[row + 1][col + 1] == emblem[1][1]) pre_num++;
            }

            // 文字を変更して追加パターン数を計算
            for (int i = 0; i < 3; i++) {
                map[row][col] = array[i];

                int tmp_num = 0;
                if (row - 1 >= 0 && col - 1 >= 0) {
                    if (map[row - 1][col - 1] == emblem[0][0] && map[row - 1][col] == emblem[0][1] &&
                        map[row][col - 1] == emblem[1][0] && map[row][col] == emblem[1][1]) tmp_num++;
                }
                if (row - 1 >= 0 && col + 1 <= W - 1) {
                    if (map[row - 1][col] == emblem[0][0] && map[row - 1][col + 1] == emblem[0][1] &&
                        map[row][col] == emblem[1][0] && map[row][col + 1] == emblem[1][1]) tmp_num++;
                }
                if (row + 1 <= H - 1 && col - 1 >= 0) {
                    if (map[row][col - 1] == emblem[0][0] && map[row][col] == emblem[0][1] &&
                        map[row + 1][col - 1] == emblem[1][0] && map[row + 1][col] == emblem[1][1]) tmp_num++;
                }
                if (row + 1 <= H - 1 && col + 1 <= W - 1) {
                    if (map[row][col] == emblem[0][0] && map[row][col + 1] == emblem[0][1] &&
                        map[row + 1][col] == emblem[1][0] && map[row + 1][col + 1] == emblem[1][1]) tmp_num++;
                }

                max_add = max(max_add, tmp_num - pre_num);
            }

            // 元の文字に戻す
            map[row][col] = pre_char;
        }
    }

    // 最終結果を出力
    printf("%d\n", base + max_add);

    // 動的配列の解放
    for (int i = 0; i < H; i++) delete[] map[i];
    delete[] map;

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3984
final_rank: 1

code_snippet: #line 1 "/opt/library/template.hpp"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'001'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
#define inf infty<ll>

using pi = pair<ll, ll>;
using vi = vector<ll>;
using vvi = vector<vector<ll>>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

#define rep1(a) for (ll _ = 0; _ < (ll)(a); ++_)
#define rep2(i, a) for (ll i = 0; i < (ll)(a); ++i)
#define rep3(i, a, b) for (ll i = a; i < (ll)(b); ++i)
#define rep4(i, a, b, c) for (ll i = a; i < (ll)(b); i += (c))
#define rrep1(a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep2(i, a) for (ll i = (a)-1; i >= (ll)(0); --i)
#define rrep3(i, a, b) for (ll i = (b)-1; i >= (ll)(a); --i)
#define rrep4(i, a, b, c) for (ll i = (b)-1; i >= (ll)(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload4(__VA_ARGS__, rrep4, rrep3, rrep2, rrep1)(__VA_ARGS__)

#define all(x) (x).begin(),(x).end()
#define len(x) (ll)(x.size())
#define elif else if
#define bit(x, i) (((x)>>(i))&1)

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll
#define abs llabs

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) \
  sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()

ll popcnt(ll x) { return __builtin_popcountll(x); }
ll popcnt(u64 x) { return __builtin_popcountll(x); }
ll popcnt_mod_2(ll x) { return __builtin_parityll(x); }
ll popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
ll topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
ll lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
ll lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
  return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template<typename T> T SUM(const vector<T> &A) {
  T s = 0; for (auto &&a: A) s += a;
  return s;
}

template <typename T>
T POP(queue<T> &que) {
  T a = que.front();
  que.pop();
  return a;
}
template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <typename T>
T POP(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(pqg<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}
template <typename F>
f128 binary_search_real(F check, f128 ok, f128 ng, ll iter = 100) {
  rep(iter) {
    f128 x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  rep(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(vc<U> &A, ll off = 1) {
  ll N = A.size();
  vc<T> B(N + 1);
  rep(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vi argsort(const vector<T> &A) {
  vi ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
       [&](ll i, ll j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vi &I) {
  vc<T> B(len(I));
  rep(i, len(I)) B[i] = A[I[i]];
  return B;
}

template<typename T> inline bool chmax(T &a, T b) {return ((a<b)?(a=b,true):(false));}
template<typename T> inline bool chmin(T &a, T b) {return ((a>b)?(a=b,true):(false));}

inline void wt(const char c) { cout << c; }
inline void wt(const string s) { cout << s; }
inline void wt(const char *s) { cout << s; }

template <typename T>
void wt_integer(T x) {
  if (x < 0) { cout << (i64)(x); }
  else { cout << (u64)(x); }
}
template <typename T>
void wt_real(T x) {
  cout << fixed << setprecision(15) << (long double)(x);
}

inline void wt(int x) { wt_integer(x); }
inline void wt(ll x) { wt_integer(x); }
inline void wt(i128 x) { wt_integer(x); }
inline void wt(u32 x) { wt_integer(x); }
inline void wt(u64 x) { wt_integer(x); }
inline void wt(u128 x) { wt_integer(x); }
inline void wt(double x) { wt_real(x); }
inline void wt(long double x) { wt_real(x); }
inline void wt(f128 x) { wt_real(x); }

template <class T, class U>
void wt(const pair<T, U> val) {
  wt(val.first); wt(' '); wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
  if constexpr (N < std::tuple_size<T>::value) {
    if constexpr (N > 0) { wt(' '); }
    const auto x = std::get<N>(t);
    wt(x);
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(tuple<T...> tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  wt(head);
  if (sizeof...(Tail)) wt(' ');
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void onez(bool t = 1) { print(t ? 1 : 0); }
#define endl '\n'
#define dump(x) {cerr << #x " = " << x << '\n';}
#line 2 "main.cpp"

int solve();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  while (!solve()) {break;}
  return 0;
}

int solve() {
  ll M, N;
  cin >> M >> N;
  vc<string> A(M), B(2);
  rep(i, M) cin >> A[i];
  rep(i, 2) cin >> B[i];
  vvv(ll, c, M, N, 3, 0);
  map<char,ll> d;
  d['J'] = 0;
  d['O'] = 1;
  d['I'] = 2;
  ll ans = 0;
  rep(i, M-1) rep(j, N-1) {
    ll diff = 0;
    ll dy = -1;
    ll dx = -1;
    rep(x, 2) rep(y, 2) {
      if (A[i+y][j+x] != B[y][x]) {
        diff++;
        dy = y;
        dx = x;
      }
    }
    if (diff == 0) {
      ans++;
    } elif (diff == 1) {
      c[i+dy][j+dx][d[B[dy][dx]]]++;
    }
  }
  ll max_diff = 0;
  rep(i, M) rep(j, N) rep(k, 3) chmax(max_diff, c[i][j][k]);
  ans += max_diff;
  print(ans);
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 59044
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

ll modPow(long long a, long long n, long long p) {
    if (n == 0) return 1; // 0乗にも対応する場合
    if (n == 1) return a % p;
    if (n % 2 == 1) return (a * modPow(a, n - 1, p)) % p;
    long long t = modPow(a, n / 2, p);
    return (t * t) % p;
}


ll gcd(ll(a), ll(b)) {
    if (a == 0)return b;
    if (b == 0)return a;
    ll c = a;
    while (a % b != 0) {
        c = a % b;
        a = b;
        b = c;
    }
    return b;
}
ll sqrtz(ll N) {
    ll L = 0;
    ll R = sqrt(N) + 10000;
    while (abs(R - L) > 1) {
        ll mid = (R + L) / 2;
        if (mid * mid <= N)L = mid;
        else R = mid;
    }
    return L;

}




ll M,N;
vector<vector<char>> C,P(2,vector<char>(2));

ll all_match(){
    ll h=C.size();
    ll w=C[0].size();
    ll res=0;
    rep(i,h-1)rep(j,w-1){
        ll cnt=0;
        rep(y,2)rep(x,2)if(C[i+y][j+x]==P[y][x])cnt++;
        if(cnt==4)res++;
    }
    return res;
}

ll match(ll a,ll b){
    ll res=0;
    rep(i,2)rep(j,2){
        ll cnt=0;
        rep(y,2)rep(x,2)if(C[a-1+i+y][b-1+j+x]==P[y][x])cnt++;
        if(cnt==4)res++;
    }
    return res;
}


int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    cin>>M>>N;
    C.assign(M+2,vector<char>(N+2,'?'));
    rep(i,M){
        string S;
        cin>>S;
        rep(j,N)C[i+1][j+1]=S[j];
    }
    rep(p,2){
        string S;
        cin>>S;
        rep(q,2)P[p][q]=S[q];
    }
    ll an=all_match();
    ll bn=an;
    string T="JOI";
    for(ll h=1;h<=M;h++)for(ll w=1;w<=N;w++){
        char moto=C[h][w];
        rep(k,3){
            ll res=match(h,w);
            C[h][w]=T[k];
            res-=match(h,w);
            chmax(bn,an-res);
            C[h][w]=moto;
        }
        
    }
    cout<<bn<<endl;

    
}
accuracy: 1
time_ms: 160
memory_kb: 4544
final_rank: 17

code_snippet: #define _USE_MATH_DEFINES
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<string>
#include<iomanip>
#include<numeric>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<random>
#include<bitset>
#include<cassert>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int dx[]={1,0,0,-1},dy[]={0,1,-1,0};
int main(){
	int m,n;
	string a[1000],b[2];
	cin>>m>>n;
	for(int i=0;i<m;i++)
		cin>>a[i];
	cin>>b[0]>>b[1];
	int cnt=0;
	for(int i=0;i<m-1;i++){
		for(int j=0;j<n-1;j++){
			bool f=1;
			for(int i2=0;i2<2;i2++)
				for(int j2=0;j2<2;j2++)
					if(a[i+i2][j+j2]!=b[i2][j2])
						f=0;
			if(f)
				cnt++;
		}
	}
	int ans=cnt;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			for(int k=0;k<3;k++){
				char c=a[i][j];
				int tmp=cnt;
				for(int i2=i-1;i2<=i;i2++){
					for(int j2=j-1;j2<=j;j2++){
						if(0<=i2&&i2<m-1&&0<=j2&&j2<n-1){
							bool f=1;
							for(int i3=0;i3<2;i3++)
								for(int j3=0;j3<2;j3++)
									if(a[i2+i3][j2+j3]!=b[i3][j3])
										f=0;
							if(f)
								tmp--;
						}
					}
				}
				a[i][j]="JOI"[k];
				for(int i2=i-1;i2<=i;i2++){
					for(int j2=j-1;j2<=j;j2++){
						if(0<=i2&&i2<m-1&&0<=j2&&j2<n-1){
							bool f=1;
							for(int i3=0;i3<2;i3++)
								for(int j3=0;j3<2;j3++)
									if(a[i2+i3][j2+j3]!=b[i3][j3])
										f=0;
							if(f)
								tmp++;
						}
					}
				}
				ans=max(ans,tmp);
				a[i][j]=c;
			}
		}
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 90
memory_kb: 5348
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define all(v) v.begin(), v.end()
#define rep(i, begin, end) for(auto i = (begin); i < (end); i++)
#define rrep(i, end, begin) for(auto i = (end) - 1; i >= (begin); i--)
template<class T> inline bool chmin(T& a, T b){ if (a > b){ a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b){ if (a < b){ a = b; return true; } return false; }
template<class T> inline T roundup(T a, T b){ return (a + b - 1) / b; }
constexpr int dy[] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
constexpr int dx[] = {1, 0, -1, 0, 1, -1, 1, -1, 0};
using ll = long long;
constexpr ll INF = 1e9;
/* #include <atcoder/all>
using namespace atcoder;
using mint = modint1000000007;
ostream& operator<<(ostream& os, const mint& n){ os << n.val(); return os; }
istream& operator>>(istream& is, mint& n){ ll m; is >> m; n = m; return is; } */
struct Edge{ int to; ll cost; Edge(int to, ll cost) : to(to), cost(cost) {} };
using Graph = vector<vector<int>>;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    int h, w;
    cin >> h >> w;
    vector a(h, vector(w, '.'));
    rep(i, 0, h) rep(j, 0, w) cin >> a[i][j];
    vector t(2, vector(2, '.'));
    rep(i, 0, 2) rep(j, 0, 2) cin >> t[i][j];
    
    // 元のスコア
    int base = 0;
    rep(i, 0, h - 1) rep(j, 0, w - 1){
        bool ok = true;
        rep(k, 0, 2) rep(l, 0, 2) if(t[k][l] != a[i + k][j + l]) ok = false;
        base += ok;
    }
    int ans = base;
    // 変える位置と文字を全探索
    string joi = "JOI";
    rep(i, 0, h) rep(j, 0, w) for(const auto& ch : joi){
        int cand = base;
        // (i, j) を含む紋章の数[変更前]
        int cnt = 0;
        bool ok = true;
        if(i > 0 && j > 0){
            rep(y, -1, 1) rep(x, -1, 1){
                if(t[y + 1][x + 1] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i < h - 1 && j < w - 1){
            ok = true;
            rep(y, 0, 2) rep(x, 0, 2){
                if(t[y][x] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i > 0 && j < w - 1){
            ok = true;
            rep(y, -1, 1) rep(x, 0, 2){
                if(t[y + 1][x] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i < h - 1 && j > 0){
            ok = true;
            rep(y, 0, 2) rep(x, -1, 1){
                if(t[y][x + 1] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        cand -= cnt;
        
        char pch = a[i][j];
        a[i][j] = ch;
        // (i, j) を含む紋章の数[変更後]
        cnt = 0;
        if(i > 0 && j > 0){
            ok = true;
            rep(y, -1, 1) rep(x, -1, 1){
                if(t[y + 1][x + 1] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i < h - 1 && j < w - 1){
            ok = true;
            rep(y, 0, 2) rep(x, 0, 2){
                if(t[y][x] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i > 0 && j < w - 1){
            ok = true;
            rep(y, -1, 1) rep(x, 0, 2){
                if(t[y + 1][x] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        if(i < h - 1 && j > 0){
            ok = true;
            rep(y, 0, 2) rep(x, -1, 1){
                if(t[y][x + 1] != a[i + y][j + x]) ok = false;
            }
            cnt += ok;
        }
        cand += cnt;
        chmax(ans, cand);
        a[i][j] = pch;
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 70
memory_kb: 4468
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long MOD1 = 1000000007;
const long long MOD2 = 998244353;
typedef long long ll;
//typedef int ll;
typedef pair<ll, ll> P;
const long long INF = 1e10;
template <typename T>
void input_arr(vector<T>& A, ll N) {
	for (ll i = 0; i < N; i++) {
		cin >> A[i];
	}
}
template <typename T, typename Q>
void input_arr(vector<pair<T, Q>>& A, ll N) {
	for (ll i = 0; i < N; i++) {
		cin >> A[i].first >> A[i].second;
	}
}
template <typename T>
void input_arr(vector<vector<T>>& A, ll H, ll W) {
	for (ll i = 0; i < H; i++) {
		for (ll j = 0; j < W; j++) {
			cin >> A[i][j];
		}
	}
}
bool check(vector<string>&S, vector<string>&T, ll sx, ll sy, char ch, ll x, ll y) {
    for (ll i = 0; i <= 1; i++) {
        for (ll j = 0; j <= 1; j++) {
            if (sx+i == x && sy+j == y) {
                if (T[i][j] != ch) return false;
            }
            else {
                if (T[i][j] != S[sx + i][sy + j]) return false;
            }
        }
    }
    return true;
}
void solve() {
    ll N, M; cin >> M >> N;
    vector<string>S(M); input_arr(S, M);
    vector<string>T(2); input_arr(T, 2);
    ll sum = 0;
    for (ll i = 0; i < M - 1; i++) {
        for (ll j = 0; j < N - 1; j++) {
            sum += check(S, T, i, j, S[i][j], i, j);
        }
    }
    ll dx[4] = {-1, -1, 0, 0}, dy[4] = {0, -1, 0, -1};
    char ch[3] = {'J', 'O', 'I'};
    ll sum2 = 0;
    for (ll i = 0; i < M; i++) {
        for (ll j = 0; j < N; j++) {
            for (ll k = 0; k < 3; k++) {
                ll num = 0;
                for (ll m = 0; m < 4; m++) {
                    ll x = i + dx[m], y = j + dy[m];
                    if (x < 0 || x >= M -1 || y < 0 || y >= N - 1) continue;
                    if (!check(S, T, x, y, S[i][j], i, j) && check(S, T, x, y, ch[k], i, j)) num++;
                    else if (check(S, T, x, y, S[i][j], i, j) && !check(S, T, x, y, ch[k], i, j)) num--;
                }
                sum2 = max(sum2, num);
            }
        }
    }
    cout <<sum + sum2 << endl;
}
int main() {
    ll T=1; //cin >> T;
    while (T--) solve();
}
accuracy: 1
time_ms: 150
memory_kb: 5368
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define drep(i,j,n) for(int i=0;i<(int)(n-1);i++)for(int j=i+1;j<(int)(n);j++)
#define trep(i,j,k,n) for(int i=0;i<(int)(n-2);i++)for(int j=i+1;j<(int)(n-1);j++)for(int k=j+1;k<(int)(n);k++)
#define codefor int test;scanf("%d",&test);while(test--)
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define yes(ans) if(ans)printf("yes\n");else printf("no\n")
#define Yes(ans) if(ans)printf("Yes\n");else printf("No\n")
#define YES(ans) if(ans)printf("YES\n");else printf("NO\n")
#define popcount(v) __builtin_popcount(v)
#define vector2d(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define vector3d(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
using namespace std;
using ll = long long;
template<class T> using rpriority_queue = priority_queue<T, vector<T>, greater<T>>;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=1LL<<60;
void scan(int& a){scanf("%d",&a);}
void scan(long long& a){scanf("%lld",&a);}
template<class T,class L>void scan(pair<T, L>& p){scan(p.first);scan(p.second);}
template<class T,class U,class V>void scan(tuple<T,U,V>& p){scan(get<0>(p));scan(get<1>(p));scan(get<2>(p));}
template<class T> void scan(T& a){cin>>a;}
template<class T> void scan(vector<T>& vec){for(auto&& it:vec)scan(it);}
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){scan(head);in(tail...);}
void print(const int& a){printf("%d",a);}
void print(const long long& a){printf("%lld",a);}
void print(const double& a){printf("%.15lf",a);}
template<class T,class L>void print(const pair<T, L>& p){print(p.first);putchar(' ');print(p.second);}
template<class T> void print(const T& a){cout<<a;}
template<class T> void print(const vector<T>& vec){if(vec.empty())return;print(vec[0]);for(auto it=vec.begin();++it!= vec.end();){putchar(' ');print(*it);}}
void out(){putchar('\n');}
template<class T> void out(const T& t){print(t);putchar('\n');}
template <class Head, class... Tail> void out(const Head& head,const Tail&... tail){print(head);putchar(' ');out(tail...);}
template<class T> void dprint(const T& a){cerr<<a;}
template<class T> void dprint(const vector<T>& vec){if(vec.empty())return;cerr<<vec[0];for(auto it=vec.begin();++it!= vec.end();){cerr<<" "<<*it;}}
void debug(){cerr<<endl;}
template<class T> void debug(const T& t){dprint(t);cerr<<endl;}
template <class Head, class... Tail> void debug(const Head& head, const Tail&... tail){dprint(head);cerr<<" ";debug(tail...);}
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
ll modinv(ll a, ll m) {ll b = m, u = 1, v = 0;while (b) {ll t = a / b;a -= t * b; swap(a, b);u -= t * v; swap(u, v);}u %= m;if (u < 0) u += m;return u;}
ll updivide(ll a,ll b){return (a+b-1)/b;}
template<class T> void chmax(T &a,const T b){if(b>a)a=b;}
template<class T> void chmin(T &a,const T b){if(b<a)a=b;}

int main(){
    INT(h,w);
    vector<string> A(h),B(2);
    in(A,B);
    int cnt=0,ans=0,d1,d2;
    rep(y,h-1){
        rep(x,w-1){
            cnt+=(A[y][x]==B[0][0]&&A[y][x+1]==B[0][1]
                    &&A[y+1][x]==B[1][0]&&A[y+1][x+1]==B[1][1]);
        }
    }
    chmax(ans,cnt);
    vector<char> C={'J','O','I'};
    rep(y,h){
        rep(x,w){
            char pre=A[y][x];
            d1=d2=0;
            for(int dy=-1;dy<=0;dy++){
                for(int dx=-1;dx<=0;dx++){
                    if(y+dy<0||x+dx<0||y+dy+1>=h||x+dx+1>=w)continue;
                    d1+=(A[y+dy][x+dx]==B[0][0]&&A[y+dy][x+dx+1]==B[0][1]
                        &&A[y+dy+1][x+dx]==B[1][0]&&A[y+dy+1][x+dx+1]==B[1][1]);
                }
            }
            rep(i,3){
                A[y][x]=C[i];
                d2=0;
                for(int dy=-1;dy<=0;dy++){
                    for(int dx=-1;dx<=0;dx++){
                        if(y+dy<0||x+dx<0||y+dy+1>=h||x+dx+1>=w)continue;
                        d2+=(A[y+dy][x+dx]==B[0][0]&&A[y+dy][x+dx+1]==B[0][1]
                            &&A[y+dy+1][x+dx]==B[1][0]&&A[y+dy+1][x+dx+1]==B[1][1]);
                    }
                }
                chmax(ans,cnt-d1+d2);
            }
            A[y][x]=pre;
        }
    }
    out(ans);
}
accuracy: 1
time_ms: 70
memory_kb: 5464
final_rank: 12

code_snippet: #include<iostream>

using namespace std;

int m, n;
char f[1000][1000];
char c[2][2];

pair<int, pair<int, int>> Compare(int i,int j)
{
	if (i < 0 || i >= m - 1 || j < 0 || j >= n - 1)
		return make_pair(5, make_pair(-1, -1));

	int diff = 0;
	pair<int, int> pos_diff = make_pair(-1, -1);
	if (f[i][j] != c[0][0])
	{
		diff++;
		pos_diff = make_pair(i, j);
	}
	if (f[i][j + 1] != c[0][1])
	{
		diff++;
		pos_diff = make_pair(i, j + 1);
	}
	if (f[i + 1][j] != c[1][0])
	{
		diff++;
		pos_diff = make_pair(i + 1, j);
	}
	if (f[i + 1][j + 1] != c[1][1])
	{
		diff++;
		pos_diff = make_pair(i + 1, j + 1);
	}

	return make_pair(diff, pos_diff);
}

int main()
{
	cin >> m >> n;
	for (int i = 0; i < m; i++)
		for (int j = 0;j < n; j++)
			cin >> f[i][j];
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 2; j++)
			cin >> c[i][j];
	int ans = 0;
	int maxDelta = 0;
	for (int i = 0; i < m - 1; i++)
	{
		for (int j = 0; j < n - 1; j++)
		{
			pair<int,pair<int,int>> res = Compare(i, j);
			int diff = res.first;
			ans += (diff == 0);
			if (diff == 1)
			{
				int di = res.second.first;
				int dj = res.second.second;
				int before = (Compare(di - 1, dj - 1).first == 0) + (Compare(di - 1, dj).first == 0)
					+ (Compare(di, dj - 1).first == 0) + (Compare(di, dj).first == 0);
				int tmp = f[di][dj];
				f[di][dj] = c[di - i][dj - j];
				int after = (Compare(di - 1, dj - 1).first == 0) + (Compare(di - 1, dj).first == 0)
					+ (Compare(di, dj - 1).first == 0) + (Compare(di, dj).first == 0);

				maxDelta = max(maxDelta, after - before);
				f[di][dj] = tmp;
			}
		}
	}
	ans += maxDelta;
	cout << ans << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 4108
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    int h,w;
    cin >> h >> w;
    vector<vector<char>> g(h+2, vector<char>(w+2, 0));
    for(int i=1; i<=h; i++){
        for(int j=1; j<=w; j++){
            cin >> g[i][j];
        }
    }
    vector<vector<char>> ptn(2, vector<char>(2));
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            cin >> ptn[i][j];
        }
    }
    int num = 0;
    int diff = 0;
    vector<char> d{'J', 'O', 'I'};
    for(int i=1; i<=h; i++){
        for(int j=1; j<=w; j++){
            d.push_back(g[i][j]);
            for(int c=0; c<4; c++){
                g[i][j] = d[c];
                int sub = 0;
                for(int k=-1; k<=0; k++){
                    for(int l=-1; l<=0; l++){
                        bool ok = true;
                        for(int x=0; x<2; x++){
                            for(int y=0; y<2; y++){
                                if(g[i+k+x][j+l+y] != ptn[x][y]){
                                    ok = false;
                                    break;
                                }
                            }
                        }
                        if(ok){
                            if(c == 3){
                                num++;
                            }else if(d[c] != d[3]){
                                sub++;
                            }
                        }
                    }
                }
                diff = max(diff, sub);
            }
            d.pop_back();
        }
    }
    cout << num/4 + diff << endl;
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 4472
final_rank: 15

code_snippet: #pragma region Macros
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define drep(i,n) for(ll i = n-1;i >= 0;i--)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define endl '\n'
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)\
    vector<type> name(size);\
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)\
    vector<vector<type>> name(h, vector<type>(w));\
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)\
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)\
    int __VA_ARGS__;\
    IN(__VA_ARGS__)
#define LL(...)\
    ll __VA_ARGS__;\
    IN(__VA_ARGS__)
#define STR(...)\
    string __VA_ARGS__;\
    IN(__VA_ARGS__)
#define CHR(...)\
    char __VA_ARGS__;\
    IN(__VA_ARGS__)
#define DBL(...)\
    double __VA_ARGS__;\
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}
#define i128 __int128_t
#define ull unsigned long long int
template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
template <typename A, typename B>
ostream& operator <<(ostream& out, const pair<A, B>& a) {
out << "(" << a.first << "," << a.second << ")";
return out;
}
template <typename T, size_t N>
ostream& operator <<(ostream& out, const array<T, N>& a) {
out << "["; bool first = true;
for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
return out;
}
template <typename T>
ostream& operator <<(ostream& out, const vector<T>& a) {
out << "["; bool first = true;
for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
return out;
}
template <typename T, class Cmp>
ostream& operator <<(ostream& out, const set<T, Cmp>& a) {
out << "{"; bool first = true;
for (auto& v : a) { out << (first ? "" :", "); out << v; first = 0;} out << "}";
return out;
}
template <typename U, typename T, class Cmp>
ostream& operator <<(ostream& out, const map<U, T, Cmp>& a) {
out << "{"; bool first = true;
for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}";
return out;
}
#define LOCAL
#ifdef LOCAL
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
#else
#define trace(...) 42
#endif
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
const char* comma = strchr(names + 1, ',');
cerr.write(names, comma - names) << ": " << arg1 << " |";
__f(comma + 1, args...);
}
#pragma endregion
//#include<atcoder/all>
//using namespace atcoder;
int main(){
    INT(h,w);
    vector<string> f(h);
    rep(i,h)cin >> f[i];
    vector<string> joi(2);
    rep(i,2)cin >> joi[i];
    auto check = [&](pii a,pii b,pii c,pii d){
        auto valid = [&](int x,int y){
            return x >= 0 && y >= 0 && x < h && y < w;
        };
        {
            auto [x,y] = a;
            if(!valid(x,y))return false;
            if(f[x][y] != joi[0][0])return false;
        }
        {
            auto [x,y] = b;
            if(!valid(x,y))return false;
            if(f[x][y] != joi[1][0])return false;
        }
        {
            auto [x,y] = c;
            if(!valid(x,y))return false;
            if(f[x][y] != joi[0][1])return false;
        }
        {
            auto [x,y] = d;
            if(!valid(x,y))return false;
            if(f[x][y] != joi[1][1])return false;
        }
        return true;
    };  
    int sum = 0;
    rep(i,h)rep(j,w){
        if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))sum++;
    }
    // trace(ret);
    ll ret = 0;
    rep(i,h)rep(j,w){
        //[i,j]
        {
            ll tmp = sum;
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp--;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp--;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp--;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp--;
            char c = f[i][j];
            f[i][j] = 'J';
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp++;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp++;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp++;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp++;
            chmax(ret,tmp);
            f[i][j] = c;
        }
        {
            ll tmp = sum;
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp--;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp--;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp--;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp--;
            char c = f[i][j];
            f[i][j] = 'O';
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp++;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp++;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp++;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp++;
            chmax(ret,tmp);
            f[i][j] = c;
        }
        {
            ll tmp = sum;
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp--;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp--;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp--;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp--;
            char c = f[i][j];
            f[i][j] = 'I';
            if(check({i,j},{i+1,j},{i,j+1},{i+1,j+1}))tmp++;
            if(check({i-1,j-1},{i,j-1},{i-1,j},{i,j}))tmp++;
            if(check({i,j-1},{i+1,j-1},{i,j},{i+1,j}))tmp++;
            if(check({i-1,j},{i,j},{i-1,j+1},{i,j+1}))tmp++;
            chmax(ret,tmp);
            f[i][j] = c;
        }
    }
    cout << ret << endl;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 4440
final_rank: 7

code_snippet: #include<cstdio>
#include<algorithm>
using namespace std;
int x[1000][1000][3]={0};
char a[1000][1001],b[2][3],c[4]="JOI";
int main(void)
{
	int cnt,m,n,ans=0,mx,i,j,flg,k;
	scanf("%d %d",&n,&m);
	for(i=0;i<n;i++)	scanf("%s",a[i]);
	scanf("%s %s",b[0],b[1]);
	for(i=0;i<n-1;i++){
		for(j=0;j<m-1;j++){	
			cnt=0;	flg=0;
			if(a[i][j]==b[0][0])	cnt++;
			else	flg=1;
			if(a[i][j+1]==b[0][1])	cnt++;
			else	flg=2;
			if(a[i+1][j]==b[1][0])	cnt++;
			else	flg=3;
			if(a[i+1][j+1]==b[1][1])	cnt++;
			else	flg=4;	
			if(cnt==4){
				ans++;
				for(k=0;k<3;k++){
					if(c[k]!=a[i][j]){
						x[i][j][k]--;
					}
					if(c[k]!=a[i][j+1]){
						x[i][j+1][k]--;
					}
					if(c[k]!=a[i+1][j]){
						x[i+1][j][k]--;
					}
					if(c[k]!=a[i+1][j+1]){
						x[i+1][j+1][k]--;
					}
				}
			}
			if(cnt==3){
				if(flg==1){
					if(b[0][0]=='J')	x[i][j][0]++;
					if(b[0][0]=='O')	x[i][j][1]++;
					if(b[0][0]=='I')	x[i][j][2]++;
				}
				if(flg==2){
					if(b[0][1]=='J')	x[i][j+1][0]++;
					if(b[0][1]=='O')	x[i][j+1][1]++;
					if(b[0][1]=='I')	x[i][j+1][2]++;
				}
				if(flg==3){
					if(b[1][0]=='J')	x[i+1][j][0]++;
					if(b[1][0]=='O')	x[i+1][j][1]++;
					if(b[1][0]=='I')	x[i+1][j][2]++;
				}
				if(flg==4){
					if(b[1][1]=='J')	x[i+1][j+1][0]++;
					if(b[1][1]=='O')	x[i+1][j+1][1]++;
					if(b[1][1]=='I')	x[i+1][j+1][2]++;
				}
			}
		}
	}
	mx=ans;
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			for(k=0;k<3;k++){
				mx=max(mx,ans+x[i][j][k]);
			}
		}
	}
	printf("%d\n",mx);
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 15448
final_rank: 4

code_snippet: // clang-format off
//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define stoi stoll
#define Endl endl
#define itn int
#define fi first
#define se second
#define rep(i, n) for(int i=0, i##_len=(n); i<i##_len; i++)
#define rep2(i, a, b) for (int i = (int)(a), i##_len=(b); i < i##_len; i++)
#define rep3(i, a, b) for (int i = (int)(a), i##_len=(b); i >= i##_len; i--)
#define FOR(i, a) for (auto &i: a)
#define ALL(obj) begin(obj), end(obj)
#define _max(x) *max_element(ALL(x))
#define _min(x) *min_element(ALL(x))
#define _sum(x) accumulate(ALL(x), 0LL)
#define LOWER_BOUND(A, key) distance(begin(A), lower_bound(ALL(A), key))
#define UPPER_BOUND(A, key) distance(begin(A), upper_bound(ALL(A), key))

const int MOD   = 1000000007;
// const int MOD    = 998244353;
const int INF    = (int)(1e13 + 7);
const double EPS = 1e-8;
const double PI  = 3.14159265358979;
template <class T> using V = vector<T>;
template <class T> using VV = vector<vector<T>>;
template <class T> using VVV = vector<vector<vector<T>>>;
template <class T, class S>  using P = pair<T, S>;
template<class T> bool chmax(T &a, const T &b) {if (a < b) {a = b;return true;}return false;}
template<class T> bool chmin(T &a, const T &b) {if (b < a) {a = b;return true;}return false;}
int _ceil(int a, int b) { return (a >= 0 ? (a + (b - 1)) / b : (a - (b - 1)) / b); }
int _mod(int &a) {a = a >= 0 ? a % MOD : a - (MOD * _ceil(a, MOD));return a;}
int _pow(int a, int b) {int res = 1;for (a %= MOD; b; a = a * a % MOD, b >>= 1)if (b & 1) res = res * a % MOD;return res;}
struct mint {long long x;mint(long long x = 0) : x((x % MOD + MOD) % MOD) {}mint operator-() const { return mint(-x); }mint &operator+=(const mint a) {if ((x += a.x) >= MOD) x -= MOD;return *this;}mint &operator-=(const mint a) {if ((x += MOD - a.x) >= MOD) x -= MOD;return *this;}mint &operator*=(const mint a) { (x *= a.x) %= MOD;return *this; }mint operator+(const mint a) const { return mint(*this) += a; }mint operator-(const mint a) const { return mint(*this) -= a; } mint operator*(const mint a) const { return mint(*this) *= a; }mint pow(long long t) const {if (!t) return 1;mint a = pow(t >> 1);a *= a;if (t & 1) a *= *this;return a;}mint inv() const { return pow(MOD - 2); }mint &operator/=(const mint a) { return *this *= a.inv(); }mint operator/(const mint a) const { return mint(*this) /= a; }};istream &operator>>(istream &is, mint &a) { return is >> a.x; }ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }
// clang-format on

signed main() {
  cin.tie(nullptr);
  cout.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(15);
  int M, N;
  cin >> M >> N;
  V<string> flag(M + 2);
  string ioj  = "IOJ";
  flag[0]     = string(N + 2, '#');
  flag[M + 1] = string(N + 2, '#');
  rep(i, M) cin >> flag[i + 1];
  rep(i, M) flag[i + 1] = "#" + flag[i + 1] + "#";
  V<string> mark(2);
  rep(i, 2) cin >> mark[i];
  int num = 0;
  rep2(i, 1, M + 1) rep2(j, 1, N + 1) {
    bool yes = true;
    rep(k, 2) rep(l, 2) {
      if (flag[i + k][j + l] != mark[k][l]) yes = false;
    }
    if (yes) num++;
  }
  int ans = 0;
  rep2(i, 1, M + 1) rep2(j, 1, N + 1) {
    int num_around = 0;
    rep2(k, i - 1, i + 1) rep2(l, j - 1, j + 1) {
      bool yes = true;
      rep(m, 2) rep(n, 2) {
        if (flag[k + m][l + n] != mark[m][n]) yes = false;
      }
      if (yes) num_around++;
    }
    char temp = flag[i][j];
    FOR(z, ioj) {
      flag[i][j]   = z;
      int num_temp = 0;
      rep2(k, i - 1, i + 1) rep2(l, j - 1, j + 1) {
        bool yes = true;
        rep(m, 2) rep(n, 2) {
          if (flag[k + m][l + n] != mark[m][n]) yes = false;
        }
        if (yes) num_temp++;
      }
      chmax(ans, num - num_around + num_temp);
    }
    flag[i][j] = temp;
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 5088
final_rank: 3

code_snippet: #pragma region Macros
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define drep(i,n) for(ll i = n-1;i >= 0;i--)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define endl '\n'
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)\
    vector<type> name(size);\
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)\
    vector<vector<type>> name(h, vector<type>(w));\
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)\
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)\
    int __VA_ARGS__;\
    IN(__VA_ARGS__)
#define LL(...)\
    ll __VA_ARGS__;\
    IN(__VA_ARGS__)
#define STR(...)\
    string __VA_ARGS__;\
    IN(__VA_ARGS__)
#define CHR(...)\
    char __VA_ARGS__;\
    IN(__VA_ARGS__)
#define DBL(...)\
    double __VA_ARGS__;\
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}
template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;
using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}
#define i128 __int128_t
#define ull unsigned long long int
template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
template <typename A, typename B>
ostream& operator <<(ostream& out, const pair<A, B>& a) {
out << "(" << a.first << "," << a.second << ")";
return out;
}
template <typename T, size_t N>
ostream& operator <<(ostream& out, const array<T, N>& a) {
out << "["; bool first = true;
for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
return out;
}
template <typename T>
ostream& operator <<(ostream& out, const vector<T>& a) {
out << "["; bool first = true;
for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
return out;
}
template <typename T, class Cmp>
ostream& operator <<(ostream& out, const set<T, Cmp>& a) {
out << "{"; bool first = true;
for (auto& v : a) { out << (first ? "" :", "); out << v; first = 0;} out << "}";
return out;
}
template <typename U, typename T, class Cmp>
ostream& operator <<(ostream& out, const map<U, T, Cmp>& a) {
out << "{"; bool first = true;
for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}";
return out;
}
#define LOCAL
#ifdef LOCAL
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
#else
#define trace(...) 42
#endif
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
const char* comma = strchr(names + 1, ',');
cerr.write(names, comma - names) << ": " << arg1 << " |";
__f(comma + 1, args...);
}
#pragma endregion
//#include<atcoder/all>
//using namespace atcoder;
int main(){
    INT(h,w);
    vector<string> f(h);
    rep(i,h)cin >> f[i];
    vector<string> joi(2);
    rep(i,2)cin >> joi[i];
    auto valid = [&](int x,int y){
        return x >= 0 && y >= 0 && x < h && y < w;
    };
    auto check = [&](int x,int y){
        //x,y ga hidari ue
        if(!valid(x,y))return 0;
        if(!valid(x+1,y))return 0;
        if(!valid(x,y+1))return 0;
        if(!valid(x+1,y+1))return 0;
        int cnt = 0;
        cnt += f[x][y] == joi[0][0];
        cnt += f[x+1][y] == joi[1][0];
        cnt += f[x][y+1] == joi[0][1];
        cnt += f[x+1][y+1] == joi[1][1];
        if(cnt == 4)return 1;
        return 0;
    };
    int cnt = 0;
    rep(i,h)rep(j,w){
        cnt += check(i,j);
    }
    int ret = 0;
    rep(i,h)rep(j,w){
        //(i,j),(i-1,j),(i,j-1),(i-1,j-1)
        int tmp = 0;
        tmp += check(i,j);
        tmp += check(i-1,j);
        tmp += check(i,j-1);
        tmp += check(i-1,j-1);
        cnt -= tmp;
        rep(num,4){
            char store = f[i][j];
            f[i][j] = joi[num/2][num%2];
            int hoge = 0;
            hoge += check(i,j);
            hoge += check(i-1,j);
            hoge += check(i,j-1);
            hoge += check(i-1,j-1);
            chmax(ret,cnt+hoge);
            f[i][j] = store;
        }
        cnt += tmp;
    }
    cout << ret << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4436
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// 利益: profit[n] = n コの饅頭を乗っけられるとしたときの最大利益
// mincost[n] = n コの饅頭を売れるような箱のコストの総和の最小値 
// mincost を計算する部分は、まさにナップサック問題
int main() {
    int H, W;
    cin >> H >> W;
    vector<string> fi(H), pat(2);
    for (int i = 0; i < H; ++i) cin >> fi[i];
    for (int i = 0; i < 2; ++i) cin >> pat[i];

    auto calc = [&](int i, int j) -> int {
        if (i < 0 || i+1 >= H || j < 0 || j+1 >= W) return 0;
        for (int di = 0; di <= 1; ++di) {
            for (int dj = 0; dj <= 1; ++dj) {
                if (fi[i+di][j+dj] != pat[di][dj]) return 0;
            }
        }
        return 1;
    };
    auto calc2 = [&](int i, int j) -> int {
        return calc(i-1, j-1) + calc(i-1, j) + calc(i, j-1) + calc(i, j);
    };

    int res = 0;
    for (int i = 0; i < H; ++i) 
        for (int j = 0; j < W; ++j)
            res += calc(i, j);
    int add = 0;
    for (int i = 0; i < H; ++i) {
        for (int j = 0; j < W; ++j) {
            char origin = fi[i][j];
            int before = calc2(i, j);

            string joi = "JOI";
            for (auto c: joi) {
                fi[i][j] = c;
                int after = calc2(i, j);
                chmax(add, after - before);
            }
            fi[i][j] = origin;
        }
    }
    cout << res + add << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 5368
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip> // setprecision
#include <complex> // complex
#include <math.h> 
#include <functional>
#include <cassert>
using namespace std;
using ll = long long;
using P = pair<int,int>;
constexpr ll INF = 1e18;
constexpr int inf = 1e9;
constexpr double eps = 1e-9;
constexpr ll mod = 1000000007;
// constexpr ll mod = 998244353;
const int dx[8] = {1, 0, -1, 0,1,1,-1,-1};
const int dy[8] = {0, 1, 0, -1,1,-1,1,-1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
// --------------------------------------------------------------------------


int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int H,W;
  cin >> H >> W;
  vector<string> G(H);
  for(int i=0; i<H; i++) cin >> G[i];
  vector<string> ori(2);
  for(int i=0; i<2; i++) cin >> ori[i];

  auto check = [&](int h,int w){
    for(int i=0; i<2; i++){
      for(int j=0; j<2; j++){
        if(G[h+i][w+j] != ori[i][j]) return false;
      }
    }
    return true;
  };

  auto check2 = [&](int h,int w){
    int now = 0;
    for(int k=-1; k<=0; k++){
      for(int l=-1; l<=0; l++){
        if(h+k>=0 && w+l>=0 && h+k+1<H && w+l+1<W){
          now += check(h+k,w+l);
        }
      }
    }
    return now;
  };

  int sum = 0;
  for(int i=0; i<H-1; i++){
    for(int j=0; j<W-1; j++){
      sum += check(i,j);
    }
  }
  int ans = sum;
  string str = "JOI";
  for(int i=0; i<H; i++){
    for(int j=0; j<W; j++){
      int temp = check2(i,j);
      for(int k=0; k<3; k++){
        swap(str[k],G[i][j]);
        chmax(ans,sum-temp+check2(i,j));
        swap(str[k],G[i][j]);
      }
    }
  }
  cout << ans << "\n";
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4420
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
using ld = long double;
template <typename T> using lim = numeric_limits<T>;
template <typename T> istream& operator>>(istream& is, vector<T>& a) { for(T& x : a) { is >> x; } return is; }
template <typename X, typename Y> istream& operator>>(istream& is, pair<X, Y>& p) { return is >> p.first >> p.second; }
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int m, n;
    cin >> m >> n;
    vector<string> g(m), emblem(2);
    cin >> g >> emblem;
    auto match = [&](int i, int j) {
        bool ans = true;
        for(int di = 0; di <= 1; di++) {
            for(int dj = 0; dj <= 1; dj++) {
                ans &= i + di < m and j + dj < n and g[i + di][j + dj] == emblem[di][dj];
            }
        }
        return ans;
    };
    auto matches_around = [&](int i, int j) {
        int matches = 0;
        for(int ii = max(i - 1, 0); ii <= i; ii++) {
            for(int jj = max(j - 1, 0); jj <= j; jj++) {
                matches += match(ii, jj);
            }
        }
        return matches;
    };
    int orig = 0;
    for(int i = 0; i < m - 1; i++) {
        for(int j = 0; j < n - 1; j++) {
            orig += match(i, j);
        }
    }
    int ans = orig;
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            char old = g[i][j];
            int old_matches = matches_around(i, j);
            for(char c : {'J', 'O', 'I'}) {
                g[i][j] = c;
                ans = max(ans, orig - old_matches + matches_around(i, j));
            }
            g[i][j] = old;
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 3872
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;

int M, N;
char FlagData[1000][1000];
char Emblem[2][2];
const char WhitePaper[] = { 'J','O','I' };

int calculate(int row, int col) {
	int cnt;

	cnt = 0;
	if (row + 1 < M && col + 1 < N) {
		if (FlagData[row][col] == Emblem[0][0] && FlagData[row][col + 1] == Emblem[0][1] && 
			FlagData[row + 1][col] == Emblem[1][0] && FlagData[row + 1][col + 1] == Emblem[1][1]) {
			++cnt;
		}
	}

	if (row + 1 < M && col - 1 >= 0) {
		if (FlagData[row][col - 1] == Emblem[0][0] && FlagData[row][col] == Emblem[0][1] &&
			FlagData[row + 1][col - 1] == Emblem[1][0] && FlagData[row + 1][col] == Emblem[1][1]) {
			++cnt;
		}
	}

	if (row - 1 >= 0 && col + 1 < N) {
		if (FlagData[row - 1][col] == Emblem[0][0] && FlagData[row - 1][col + 1] == Emblem[0][1] &&
			FlagData[row][col] == Emblem[1][0] && FlagData[row][col + 1] == Emblem[1][1]) {
			++cnt;
		}
	}

	if (row - 1 >= 0 && col - 1 >= 0) {
		if (FlagData[row - 1][col - 1] == Emblem[0][0] && FlagData[row - 1][col] == Emblem[0][1] &&
			FlagData[row][col - 1] == Emblem[1][0] && FlagData[row][col] == Emblem[1][1]) {
			++cnt;
		}
	}

	return cnt;
}

int solve() {
	int bCnt, aCnt, maxCnt;;
	char ch;

	maxCnt = 0;
	for (int i = 0; i < M; ++i) {
		for (int j = 0; j < N; ++j) {
			ch = FlagData[i][j];
			bCnt = calculate(i, j);
			for (int k = 0; k < 3; ++k) {
				if (ch == WhitePaper[k]) {
					continue;
				}
				FlagData[i][j] = WhitePaper[k];
				aCnt = calculate(i, j);
				maxCnt = max(maxCnt, aCnt - bCnt);
			}
			FlagData[i][j] = ch;
		}
	}

	return maxCnt;
}

int main() {
	int baseCnt;

	cin >> M >> N;
	for (int i = 0; i < M; ++i) {
		for (int j = 0; j < N; ++j) {
			cin >> FlagData[i][j];
		}
	}
	for (int i = 0; i < 2; ++i) {
		for (int j = 0; j < 2; ++j) {
			cin >> Emblem[i][j];
		}
	}
	baseCnt = 0;
	for (int i = 1; i < M; ++i) {
		for (int j = 1; j < N; ++j) {
			if (FlagData[i][j] == Emblem[1][1] && FlagData[i][j - 1] == Emblem[1][0] &&
				FlagData[i - 1][j] == Emblem[0][1] && FlagData[i - 1][j - 1] == Emblem[0][0]) {
				++baseCnt;
			}
		}
	}
	cout << baseCnt + solve() << endl;

	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 4108
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast")
#pragma GCC target("avx")
#define all(x) (x).begin(),(x).end()
#define rep(i,n) for(int (i)=0;i<(n);i++)
#define REP(i,m,n) for(int (i)=(m);(i)<(n);(i)++)
#define MOD 1000000007
#define fcout cout << fixed << setprecision(15)
#define int long long
#define endl "\n"
#define yorn(f) puts((f)?"Yes":"No")
#define YORN(f) puts((f)?"YES":"NO")
typedef long long ll;
typedef pair<int, int> P;
int gcd(int a,int b){return b?gcd(b,a%b):a;};
int lcm(int a,int b){return a/gcd(a,b)*b;};
int mod(int a,int b){return (a+b-1)/b;};
template<typename A, size_t N, typename T>
void Fill(A(&array)[N],const T &val){std::fill((T*)array,(T*)(array+N),val);}
template<class T>inline bool chmax(T& a,T b){if(a<b){a=b;return true;}return false;};
template<class T>inline bool chmin(T& a,T b){if(a>b){a=b;return true;}return false;};

string joi = "JOI";

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    
    int h, w;
    cin >> h >> w;
    vector<string> s(h), tmp(2);
    rep(i, h) cin >> s[i];
    rep(i, 2) cin >> tmp[i];

    int defcnt = 0;
    rep(i, h-1) {
        rep(j, w-1) {
            vector<string> now(2);
            now[0] = s[i].substr(j, 2);
            now[1] = s[i+1].substr(j, 2);
            if(now == tmp) defcnt++;
        }
    }

    int dif = 0;
    rep(i, h) {
        rep(j, w) {
            char focus = s[i][j];
            rep(k, 3) {
                if(focus == joi[k]) continue;
                s[i][j] = joi[k];
                int nowcnt = 0;

                REP(dy, -1, 1) {
                    int ny = i + dy;
                    REP(dx, -1, 1) {
                        // 左上
                        int nx = j + dx;
                        if(0 <= nx && nx < w-1 && 0 <= ny && ny < h-1) {
                            if(s[ny][nx] == tmp[0][0] && s[ny][nx+1] == tmp[0][1] && s[ny+1][nx] == tmp[1][0] && s[ny+1][nx+1] == tmp[1][1]) {
                                nowcnt++;
                                // cout << nx << " " << ny << endl;
                                // cout << s[ny][nx] << s[ny][nx+1] << endl;
                                // cout << s[ny+1][nx] << s[ny+1][nx+1] << endl;
                            }
                        }
                    }
                }
                chmax(dif, nowcnt);
                //cout << nowcnt << endl;

            }
            s[i][j] = focus;
        }
    }
    cout << defcnt + dif << endl;
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3948
final_rank: 19