Problem:
IOI 列車で行こう(Take the 'IOI' train)
IOI 国ではこのたび新たに鉄道を敷設した．IOI 国の鉄道を走る列車はいくつかの車両が連結されたものであり，車両には
I
,
O
の 2 種類がある．車両はそれぞれ異なる種類の車両としか連結できない．また，列車に運転席を設ける関係上，列車の両端の車両は種類
I
でなければならない．列車は車両の種類を表す文字を順につなげた文字列で表され，列車の長さはその文字列の長さであるとする．たとえば，
IOIOI
の順に車両を連結すると長さ 5 の列車を編成でき，また車両
I
は単独で長さ 1 の列車である．車両を
OIOI
や
IOOI
といった順に並べても列車を編成することはできない．
いくつかの車両が 2 つの車庫に格納されている．それぞれの車庫の中には車両が一列に並んでいる．列車を編成するときは車庫から車両を出してきて車庫前で連結していく．車庫から出せる車両は最も車庫の入り口に近い車両のみであるが，どちらの車庫から車両を出すかの順番については自由である．
列車を編成する前に，車両を好きなだけ車庫から出して別の待機用レールに移すことができる．一度待機用レールに移した車両は今後列車を編成するために使うことはできない．また，一度列車の編成を始めるとその編成が終わるまでの間は車両を車庫から待機用レールに移すことはできない．
列車を編成するとき，車庫内の全ての車両を使い切る必要はない．すなわち，列車の編成を終えた後，車庫内に使われなかった車両が残っていても構わない．
IOI 国では鉄道に乗る人がとてもたくさんいると考えられているので，できるだけ長い列車を編成したい．
図: 列車を編成している途中であり，このとき車庫にある車両を待機用レールに移すことはできない．この図は入出力例1 に対応している．
課題
車庫に格納された車両の情報が与えられたとき，編成できる列車の長さの最大値を求めるプログラムを作成せよ．それぞれの車庫に格納された車両の列は 2 種類の文字
I
,
O
のみからなる文字列で表され， 2 つの車庫の情報はそれぞれ長さ
M
の文字列
S
および長さ
N
の文字列
T
として与えられる．各文字が 1 つの車両を表し，その文字は車両の種類と同じである．文字列の1 文字目は最も車庫の入り口に近い車両を表し，末尾の文字が車庫の最も奥にある車両を表す．
制限
1 ≤
M
≤ 2000      文字列
S
の長さ
1 ≤
N
≤ 2000      文字列
T
の長さ
入力
標準入力から以下のデータを読み込め．
1 行目には
M
,
N
が空白区切りで書かれている．
2 行目には文字列
S
が書かれている．
3 行目には文字列
T
が書かれている．
出力
標準出力に，編成できる列車の長さの最大値を表す整数を 1 行で出力せよ． 列車が 1 つも編成できない場合は， 0 を出力せよ．
入出力例
入力例 1
5 5
OIOOI
OOIOI
出力例 1
7
S
によって表される車庫を車庫 S とし，
T
によって表される車庫を車庫 T としよう．このとき，たとえば車庫 S から最初の1 車両，車庫 T から最初の 2 車両を出して待機させた後，車庫 S，車庫 S，車庫 T，車庫 S，車庫 S，車庫 T，車庫 T の順番に車両を出せば，長さ7 の列車
IOIOIOI
を編成できる．
他にも，車庫 S から最初の 1 車両，車庫 T から最初の 2 車両を出して待機させた後，車庫 T，車庫 T，車庫 S，車庫 S，車庫 T，車庫 S，車庫 S の順番に車両を出すことでも長さ 7 の列車を編成できる．これより長い列車を編成することはできないので 7 を出力する．
入力例 2
5 9
IIIII
IIIIIIIII
出力例 2
1
1 つの車両のみからなる列車
I
も列車としての条件を満たすことに注意せよ．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int dp[3][2017][2017], n, m;//I, O, -
string S, T;
int main() {
	cin >> n >> m >> S >> T;
	for (int i = 0; i < 2017; i++) { for (int j = 0; j < 2017; j++) { for (int k = 0; k < 3; k++)dp[k][i][j] = -998244353; } }
	dp[2][0][0] = 0;
	for (int i = 0; i <= S.size(); i++) {
		for (int j = 0; j <= T.size(); j++) {
			if (i != S.size()) {
				if (S[i] == 'I') {
					dp[0][i + 1][j] = max(dp[0][i + 1][j], dp[1][i][j] + 1);
					dp[0][i + 1][j] = max(dp[0][i + 1][j], dp[2][i][j] + 1);
					dp[2][i + 1][j] = max(dp[2][i + 1][j], dp[2][i][j]);
				}
				if (S[i] == 'O') {
					dp[1][i + 1][j] = max(dp[1][i + 1][j], dp[0][i][j] + 1);
					dp[2][i + 1][j] = max(dp[2][i + 1][j], dp[2][i][j]);
				}
			}
			if (j != T.size()) {
				if (T[j] == 'I') {
					dp[0][i][j + 1] = max(dp[0][i][j + 1], dp[1][i][j] + 1);
					dp[0][i][j + 1] = max(dp[0][i][j + 1], dp[2][i][j] + 1);
					dp[2][i][j + 1] = max(dp[2][i][j + 1], dp[2][i][j]);
				}
				if (T[j] == 'O') {
					dp[1][i][j + 1] = max(dp[1][i][j + 1], dp[0][i][j] + 1);
					dp[2][i][j + 1] = max(dp[2][i][j + 1], dp[2][i][j]);
				}
			}
		}
	}
	int maxn = 0;
	for (int i = 0; i <= S.size(); i++) { for (int j = 0; j <= T.size(); j++)maxn = max(maxn, dp[0][i][j]); }
	cout << maxn << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 51124
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#include <vector>
using namespace std;
typedef long long ll;

int M, N;
char S[2005], T[2005];
int dp[2001][2001];

int main() {
    // 入力を受け取る
    scanf("%d%d%s%s", &M, &N, S, T); 
    int res = 0;

    // DPテーブルの初期化
    for (int i = 0; i <= M; i++) {
        for (int j = 0; j <= N; j++) {
            if ((i != 0 && S[i - 1] == 'I') || (j != 0 && T[j - 1] == 'I')) {
                dp[i][j] = 1;
            }
        }
    }

    // DPテーブルの更新
    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= N; j++) {
            // 条件1: 左上からの更新 (Iと非一致)
            if (dp[i - 1][j - 1] > 0 && S[i - 1] != T[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 2;
            }
            // 条件2: 上からの更新 (OIのペア)
            if (i >= 2 && dp[i - 2][j] > 0 && S[i - 2] == 'O' && S[i - 1] == 'I') {
                dp[i][j] = max(dp[i][j], dp[i - 2][j] + 2);
            }
            // 条件3: 左からの更新 (OIのペア)
            if (j >= 2 && dp[i][j - 2] > 0 && T[j - 2] == 'O' && T[j - 1] == 'I') {
                dp[i][j] = max(dp[i][j], dp[i][j - 2] + 2);
            }
            // 結果の最大値の更新
            res = max(res, dp[i][j]);
        }
    }

    // 結果を出力
    printf("%d\n", res);
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 19256
final_rank: 1

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int dp[2002][2002][2][2][2];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    string s, t;
    cin >> s >> t;
    for (int i = 0; i <= n + 1; ++i) {
        for (int j = 0; j <= m + 1; ++j) {
            for (int k = 0; k < 2; ++k) {
                for (int l = 0; l < 2; ++l) {
                    for (int o = 0; o < 2; ++o) {
                        dp[i][j][k][l][o] = -1;
                    }
                }
            }
        }
    }
    dp[0][0][0][0][0] = 0;
    for (int i = 0; i <= n; ++i) {
        for (int j = 0; j <= m; ++j) {
            for (int k = 0; k < 2; ++k) {
                for (int l = 0; l < 2; ++l) {
                    for (int o = 0; o < 2; ++o) {
                        int val = dp[i][j][k][l][o];
                        if (val == -1) continue;
                        if (i < n) {
                            if (!k) dp[i + 1][j][k][l][o] = max(dp[i + 1][j][k][l][o], val);
                            if (o == 0 and s[i] == 'I') {
                                dp[i + 1][j][1][l][1] = max(dp[i + 1][j][1][l][1], val + 1);
                            }
                            if (o == 1 and s[i] == 'O') {
                                dp[i + 1][j][1][l][0] = max(dp[i + 1][j][1][l][0], val + 1);
                            }
                        }
                        if (j < m) {
                            if (!l) dp[i][j + 1][k][l][o] = max(dp[i + 1][j][k][l][o], val);
                            if (o == 0 and t[j] == 'I') {
                                dp[i][j + 1][k][1][1] = max(dp[i][j + 1][k][1][1], val + 1);
                            }
                            if (o == 1 and t[j] == 'O') {
                                dp[i][j + 1][k][1][0] = max(dp[i][j + 1][k][1][0], val + 1);
                            }
                        }
                    }
                }
            }
        }
    }
    int res = 0;
    for (int i = 0; i <= n + 1; ++i) {
        for (int j = 0; j <= m + 1; ++j) {
            for (int k = 0; k < 2; ++k) {
                for (int l = 0; l < 2; ++l) {
                    for (int o = 1; o < 2; ++o) {
                        res = max(res, dp[i][j][k][l][o]);
                    }
                }
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 128716
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main() {
    int N,M;
    cin>>N>>M;
    string S,T;
    cin>>S>>T;
    reverse(S.begin(),S.end());
    reverse(T.begin(),T.end());
    vector<vector<int>> DP(N+1,vector<int>(M+1,0));
    vector<vector<int>> NDP(N+1,vector<int>(M+1,-1e9));
    for(int i=0;i<=N;i++){
        for(int j=0;j<=M;j++){
            if(DP[i][j]>=0){
                if(i<N&&S[i]=='I')NDP[i+1][j]=max(NDP[i+1][j],DP[i][j]+1);
                if(j<M&&T[j]=='I')NDP[i][j+1]=max(NDP[i][j+1],DP[i][j]+1);
            }
            if(NDP[i][j]>=0){
                if(i<N&&S[i]=='O')DP[i+1][j]=max(DP[i+1][j],NDP[i][j]+1);
                if(j<M&&T[j]=='O')DP[i][j+1]=max(DP[i][j+1],NDP[i][j]+1);
            }
        }
    }
    int an=0;
    for(int i=0;i<=N;i++)for(int j=0;j<=M;j++)if(NDP[i][j]>=0)an=max(an,NDP[i][j]);
    cout<<an<<endl;
}
accuracy: 1
time_ms: 30
memory_kb: 34520
final_rank: 2

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__)))
#define umap unordered_map
#define uset unordered_set
using namespace std;
using ll = long long;
const int MOD=1000000007;
const int MOD2=998244353;
const int INF=1<<30;
const ll INF2=(ll)1<<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){if(a%b==0) return a/b;else return (a/b)+1;}
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(n,m);
    vector3d(int,dp,n+1,m+1,2,0);
    string s,t;
    cin>>s>>t;
    //0:使用中,1:終了
    int ans=0;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k<2;k++){
                if(k==1&&dp[i][j][k]==0)continue;
                chmax(ans,dp[i][j][k]);
                bool v1=(i<n&&s[i]==(k?'O':'I'));
                bool v2=(j<m&&t[j]==(k?'O':'I'));
                if(v1)chmax(dp[i+1][j][k^1],1+dp[i][j][k]);
                if(v2)chmax(dp[i][j+1][k^1],1+dp[i][j][k]);
            }
        }
    }
    out(max(0,ans-(ans%2==0)));
}
accuracy: 1
time_ms: 210
memory_kb: 222260
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
using lli = long long int;

int main(){
    int n,m;
    string s,t;
    cin >> n >> m >> s >> t;
    vector<vector<vector<int>>> dp(n+1, vector<vector<int>>(m+1, vector<int>{0, -(n+m)}));
    for(int i=0; i<n+1; i++){
        for(int j=0; j<m+1; j++){
            if(i < n){
                if(s[i] == 'I'){
                    dp[i+1][j][1] = max(dp[i+1][j][1], dp[i][j][0]+1);
                }else{
                    dp[i+1][j][0] = max(dp[i+1][j][0], dp[i][j][1]+1);
                }
            }
            if(j < m){
                if(t[j] == 'I'){
                    dp[i][j+1][1] = max(dp[i][j+1][1], dp[i][j][0]+1);
                }else{
                    dp[i][j+1][0] = max(dp[i][j+1][0], dp[i][j][1]+1);
                }
            }
        }
    }
    int ans = 0;
    for(int i=0; i<n+1; i++){
        for(int j=0; j<m+1; j++){
            for(int d=0; d<2; d++){
                ans = max(ans, dp[i][j][d]);
            }
        }
    }
    if(ans%2 == 0 and ans > 0) ans--;
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 222236
final_rank: 18

code_snippet: #include<cstdio>
#include<algorithm>
#define w 2001
#define q (a[i]+1)%2
#define p (b[j]+1)%2
using namespace std;
int dp[w][w][2];
int main(void)
{
	int i,j,k,m,n,a[w],b[w],mx=-1;
	char s[w],t[w];
	scanf("%d %d",&m,&n);
	scanf("%s %s",s,t);
	for(i=0;i<m;i++){
		if(s[i]=='O') a[i]=0;
		else a[i]=1;
	}
	for(i=0;i<n;i++){
		if(t[i]=='O') b[i]=0;
		else b[i]=1;
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){		
			dp[i][j][0]=-1;
			dp[i][j][1]=-1;
		}
	}
	if(s[0]=='I') dp[1][0][1]=1;
	else dp[1][0][0]=0;
	if(t[0]=='I') dp[0][1][1]=1;
	else dp[0][1][0]=0;
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			if(i<m){
				if(a[i]==1){
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
				else{
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
			}
			if(j<n){
				if(b[j]==1){
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
				else{
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
			}
		}
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			for(k=0;k<2;k++) mx=max(dp[i][j][k],mx);
		}
	}
	if(mx%2==0) mx--; if(mx<0) mx=0;
	printf("%d\n",mx);
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 34056
final_rank: 6

code_snippet: #include<bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, x) for(ll i = 0; i < x; i++)
#define rep2(i, x) for(ll i = 1; i <= x; i++)
#define all(a) (a).begin(),(a).end()
using ll = long long;
using ld = long double;
using namespace std;
const ll INF = 10000000000000000;
const int intINF = 1000000000;
const ll mod = 1000000007;
const ll MOD = 998244353;
const ld pi = 3.141592653589793238;

ll dp0[2005][2005], dp1[2005][2005];
signed main() {
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	//cout << fixed << setprecision(15);

	//input
	ll n, m; cin >> n >> m;
	string s, t; cin >> s >> t;
	//if (s[0] == 'I') { dp1[1][0] = 1; }
	//if (t[0] == 'I') { dp1[0][1] = 1; }
	ll ans = 0;
	rep(i, n + 1) {
		rep(j, m + 1) {
			if (i != 0) {
				if (s[i - 1] == 'I') { dp1[i][j] = dp0[i - 1][j] + 1; }
				else if (dp1[i - 1][j] != 0) { dp0[i][j] = dp1[i - 1][j] + 1; }
			}
			if (j != 0) {
				if (t[j - 1] == 'I') { dp1[i][j] = max(dp1[i][j], dp0[i][j - 1] + 1); }
				else if (dp1[i][j - 1] != 0) { dp0[i][j] = max(dp0[i][j], dp1[i][j - 1] + 1); }
			}
			ans = max(ans, dp1[i][j]);
			//cout << i << ' ' << j << ' ' << dp0[i][j] << ' ' << dp1[i][j] << endl;
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 65920
final_rank: 13

code_snippet: #include<cstdio>
#include<algorithm>
#define w 2001
#define q (a[i]+1)%2
#define p (b[j]+1)%2
using namespace std;
int dp[w][w][2];
int main(void)
{
	int i,j,k,m,n,a[w],b[w],mx=-1;
	char s[w],t[w];
	scanf("%d %d",&m,&n);
	scanf("%s %s",s,t);
	for(i=0;i<m;i++){
		if(s[i]=='O') a[i]=0;
		else a[i]=1;
	}
	for(i=0;i<n;i++){
		if(t[i]=='O') b[i]=0;
		else b[i]=1;
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){		
			dp[i][j][0]=-1;
			dp[i][j][1]=-1;
		}
	}
	if(s[0]=='I') dp[1][0][1]=1;
	else dp[1][0][0]=0;
	if(t[0]=='I') dp[0][1][1]=1;
	else dp[0][1][0]=0;
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			if(i<m){
				if(a[i]==1){
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
				else{
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
			}
			if(j<n){
				if(b[j]==1){
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
				else{
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
			}
		}
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			for(k=0;k<2;k++) mx=max(dp[i][j][k],mx);
		}
	}
	if(mx%2==0) mx--; if(mx<0) mx=0;
	printf("%d\n",mx);
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 34060
final_rank: 7

code_snippet: #include<cstdio>
#include<algorithm>
#define w 2001
#define q (a[i]+1)%2
#define p (b[j]+1)%2
using namespace std;
int dp[w][w][2];
int main(void)
{
	int i,j,k,m,n,a[w],b[w],mx=-1;
	char s[w],t[w];
	scanf("%d %d",&m,&n);
	scanf("%s %s",s,t);
	for(i=0;i<m;i++){
		if(s[i]=='O') a[i]=0;
		else a[i]=1;
	}
	for(i=0;i<n;i++){
		if(t[i]=='O') b[i]=0;
		else b[i]=1;
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){			
			dp[i][j][0]=-1;
			dp[i][j][1]=-1;
		}
	}
	if(s[0]=='I') dp[1][0][1]=1;
	else dp[1][0][0]=0;
	if(t[0]=='I') dp[0][1][1]=1;
	else dp[0][1][0]=0;
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			if(i<m){
				if(a[i]==1){
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
				else{
					dp[i+1][j][a[i]]=max(a[i],dp[i+1][j][a[i]]);
					dp[i+1][j][a[i]]=max(dp[i][j][q]+1,dp[i+1][j][a[i]]);
				}
			}
			if(j<n){
				if(b[j]==1){
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
				else{
					dp[i][j+1][b[j]]=max(b[j],dp[i][j+1][b[j]]);
					dp[i][j+1][b[j]]=max(dp[i][j][p]+1,dp[i][j+1][b[j]]);
				}
			}
		}
	}
	for(i=0;i<=m;i++){
		for(j=0;j<=n;j++){
			for(k=0;k<2;k++){
				mx=max(dp[i][j][k],mx);
				//printf("%d.",dp[i][j][k]);
			}
			//printf(" ");
		}
		//printf("\n");
	}
	if(mx%2==0) mx--;
	if(mx<0) mx=0;
	printf("%d\n",mx);
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 34020
final_rank: 5

code_snippet: #include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 1012345678;
int main() {
	int LS, LT; string S, T;
	cin >> LS >> LT >> S >> T;
	vector<vector<pair<int, int> > > dp(LS + 1, vector<pair<int, int> >(LT + 1, make_pair(-inf, -inf)));
	for (int i = 0; i <= LS; ++i) {
		for (int j = 0; j <= LT; ++j) {
			if (i != LS && S[i] == 'I') dp[i + 1][j].first = 1;
			if (j != LT && T[j] == 'I') dp[i][j + 1].first = 1;
		}
	}
	int ans = 0;
	for (int i = 0; i <= LS; ++i) {
		for (int j = 0; j <= LT; ++j) {
			if (i >= 1) {
				if (S[i - 1] == 'I') {
					dp[i][j].first = max(dp[i][j].first, dp[i - 1][j].second + 1);
				}
				else {
					dp[i][j].second = max(dp[i][j].second, dp[i - 1][j].first + 1);
				}
			}
			if(j >= 1) {
				if (T[j - 1] == 'I') {
					dp[i][j].first = max(dp[i][j].first, dp[i][j - 1].second + 1);
				}
				else {
					dp[i][j].second = max(dp[i][j].second, dp[i][j - 1].first + 1);
				}
			}
			ans = max(ans, dp[i][j].first);
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 34388
final_rank: 8

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;
    string s, t;
    cin >> m >> n >> s >> t;
    const int N = 2000, INF = 4000;
    static int opt[N+1][N+1][2] = {};
    int ans = 0;
    for(int i = m; i >= 0; i--) {
        for(int j = n; j >= 0; j--) {
            for(bool mustI : {true, false}) {
                char req = mustI ? 'I' : 'O';
                int& cur = opt[i][j][mustI];
                cur = mustI ? -INF : 0;
                if(i < m and s[i] == req) {
                    cur = max(cur, 1 + opt[i + 1][j][not mustI]);
                }
                if(j < n and t[j] == req) {
                    cur = max(cur, 1 + opt[i][j + 1][not mustI]);
                }
            }
            ans = max({ans, opt[i][j][true]});
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 34532
final_rank: 11

code_snippet: #include<iostream>
#include<vector>

using namespace std;

constexpr int INF = (1 << 30)  - 1;

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

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int m, n;
    cin >> m >> n;

    string s, t;
    cin >> s >> t;

    vector< vector< vector< vector<int> > > > dp(3, vector< vector< vector<int> > >(2, vector< vector<int> >(m + 1, vector<int>(n + 1, -INF))));
    dp[0][0][0][0] = 0;

    for(int i = 0 ; i <= m ; ++i){
        for(int j = 0 ; j <= n ; ++j){
            if(i < m){
                chmax(dp[0][0][i + 1][j], dp[0][0][i][j]);
            }
            if(j < n){
                chmax(dp[0][0][i][j + 1], dp[0][0][i][j]);
            }

            if(i < m && s[i] == 'I'){
                chmax(dp[1][1][i + 1][j], dp[0][0][i][j] + 1);
                chmax(dp[1][1][i + 1][j], dp[1][0][i][j] + 1);
            }
            if(j < n && t[j] == 'I'){
                chmax(dp[1][1][i][j + 1], dp[0][0][i][j] + 1);
                chmax(dp[1][1][i][j + 1], dp[1][0][i][j] + 1);
            }

            if(i < m && s[i] == 'O'){
                chmax(dp[1][0][i + 1][j], dp[1][1][i][j] + 1);
            }
            if(j < n && t[j] == 'O'){
                chmax(dp[1][0][i][j + 1], dp[1][1][i][j] + 1);
            }

            chmax(dp[2][1][m][n], dp[0][0][i][j]);
            chmax(dp[2][1][m][n], dp[1][1][i][j]);
        }
    }

    cout << dp[2][1][m][n] << endl;

    cout << flush;

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 144420
final_rank: 17

code_snippet: #include <algorithm>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define REP(i, n) for (int i = 0; i < n; i++)
#define FOR(i, s, t) for (int i = s; i < t; i++)
#define ALL(obj) obj.begin(), obj.end()

const int iINF = 1e9;
const long long llINF = 1e18;
const int MOD = 1e9 + 7;
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;
}

template <int MOD>
struct ModInt {
    long long val;
    constexpr ModInt(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr ModInt operator-() const noexcept { return val ? MOD - val : 0; }
    constexpr ModInt operator+(const ModInt& r) const noexcept { return ModInt(*this) += r; }
    constexpr ModInt operator-(const ModInt& r) const noexcept { return ModInt(*this) -= r; }
    constexpr ModInt operator*(const ModInt& r) const noexcept { return ModInt(*this) *= r; }
    constexpr ModInt operator/(const ModInt& r) const noexcept { return ModInt(*this) /= r; }
    constexpr ModInt& operator+=(const ModInt& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr ModInt& operator-=(const ModInt& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr ModInt& operator*=(const ModInt& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr ModInt& operator/=(const ModInt& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b;
            swap(a, b);
            u -= t * v;
            swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator==(const ModInt& r) const noexcept { return this->val == r.val; }
    constexpr bool operator!=(const ModInt& r) const noexcept { return this->val != r.val; }
    friend constexpr ostream& operator<<(ostream& os, const ModInt<MOD>& x) noexcept { return os << x.val; }

    friend constexpr istream& operator>>(istream& is, ModInt<MOD>& x) noexcept { return is >> x.val; }
    friend constexpr ModInt<MOD> modpow(const ModInt<MOD>& a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

using mint = ModInt<MOD>;

long long modPow(long long x, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}

long long extGCD(long long a, long long b, long long& x, long long& y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }

    long long d = extGCD(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

long long gcd(long long a, long long b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

template <typename T>
map<T, int> compress(vector<T> x) {
    map<T, int> res;
    sort(x.begin(), x.end());
    x.erase(unique(x.begin(), x.end()), x.end());
    for (int i = 0; i < x.size(); i++) {
        res[x[i]] = i;
    }

    return res;
}

template <typename T>
int former(const vector<T>& v, T x) {
    return upper_bound(v.begin(), v.end(), x) - v.begin() - 1;
}

template <typename T>
int latter(const vector<T>& v, T x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin();
}

template <typename T>
using Vec = vector<T>;
template <typename T>
using VVec = vector<vector<T>>;
using LL = long long;

int dp[2010][2010][2];
int main() {
    int M, N;
    cin >> M >> N;
    string S, T;
    cin >> S >> T;
    REP(i, M) { S[i] = S[i] == 'I' ? 1 : 0; }
    REP(i, N) { T[i] = T[i] == 'I' ? 1 : 0; }
    REP(i, M + 1) REP(j, N + 1) dp[i][j][0] = 0, dp[i][j][1] = -iINF;
    REP(i, M + 1) {
        REP(j, N + 1) {
            if (i < M) chmax(dp[i + 1][j][S[i]], dp[i][j][!S[i]] + 1);
            if (j < N) chmax(dp[i][j + 1][T[j]], dp[i][j][!T[j]] + 1);
        }
    }
    int ans = 0;
    REP(i, M + 1) {
        REP(j, N + 1) {
            chmax(ans, dp[i][j][1]);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 34656
final_rank: 4

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

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int M,N;
string S,T;

ll dp[2003][2003][2];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> M >> N >> S >> T;

    for (int i = 0;i <= M;i++){
        for (int j = 0;j <= N;j++){
            dp[i][j][0] = -1;
            dp[i][j][1] = -1;
        }
    }

    dp[0][0][0] = 0;
    ll ans = 0;

    for (int i = 0;i <= M;i++){
        for (int j = 0;j <= N;j++){
            dp[i][j][0] = max(dp[i][j][0],0LL);
            //cout << i << " " << j << " " << dp[i][j][0] << " " << dp[i][j][1] << endl;
            ans = max(ans,dp[i][j][1]);
            if(dp[i][j][0] >= 0){
                if(i < M && S[i] == 'I') dp[i+1][j][1] = max(dp[i+1][j][1],dp[i][j][0]+1);
                if(j < N && T[j] == 'I') dp[i][j+1][1] = max(dp[i][j+1][1],dp[i][j][0]+1);
            }
            if(dp[i][j][1] >= 0){
                if(i < M && S[i] == 'O') dp[i+1][j][0] = max(dp[i+1][j][0],dp[i][j][1]+1);
                if(j < N && T[j] == 'O') dp[i][j+1][0] = max(dp[i][j+1][0],dp[i][j][1]+1);
            }
        }
    }

    cout << ans << endl;
    
    return 0;

}
accuracy: 1
time_ms: 40
memory_kb: 65880
final_rank: 14

code_snippet: #include<iostream>
using namespace std;

int dp[2][2001][2001] = {};

int main(){
    int n, m;
    cin >> n >> m;
    string s, t;
    cin >> s >> t;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(s[i] == 'I') dp[1][i+1][j] = 1;
            if(t[j] == 'I') dp[1][i][j+1] = 1;
        }
    }
    for(int i = 0; i <= n; i++){
        for(int j = 0; j <= m; j++){
            for(int k = 0; k < 2; k++){
                if(dp[k][i][j] == 0)    continue;
                if(i < n && s[i] == "IO"[k]) dp[1-k][i+1][j] = max(dp[1-k][i+1][j], dp[k][i][j]+1);
                if(j < m && t[j] == "IO"[k]) dp[1-k][i][j+1] = max(dp[1-k][i][j+1], dp[k][i][j]+1);
            }
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            ans = max(ans, dp[1][i][j]);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 34468
final_rank: 10

code_snippet: #include <iostream>
#include <string>
#include <vector>

using namespace std;

string s, t;
vector<vector<vector<int>>> dp;

int calc(int x, int y, bool isI) {
    int ret = 0;
    if (x < s.size() && ((s[x] == 'I') == isI)) {
        if (dp[x + 1][y][!isI] < 0) dp[x + 1][y][!isI] = calc(x + 1, y, !isI) + 1;
        ret = max(ret, dp[x + 1][y][!isI]);
    }
    if (y < t.size() && ((t[y] == 'I') == isI)) {
        if (dp[x][y + 1][!isI] < 0)dp[x][y + 1][!isI] = calc(x, y + 1, !isI) + 1;
        ret = max(ret, dp[x][y + 1][!isI]);
    }
    return ret;
}

int main() {
    int m, n;
    cin >> m >> n >> s >> t;

    int ret = 0;
    dp = vector<vector<vector<int>>>(m + 1, vector<vector<int>>(n + 1, vector<int>(2, -1)));
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            ret = max(ret, (calc(i, j, true) + 1) / 2 * 2 - 1);
        }
    }

    cout << ret << endl;
    return 0;
}
accuracy: 1
time_ms: 470
memory_kb: 222464
final_rank: 20

code_snippet: #include <bits/stdc++.h>
 
//    #include <boost/multiprecision/cpp_int.hpp>
 #define int long long
 #define inf  1000000007
 #define pa pair<int,int>
 #define ll long long
 #define pal pair<double,double>
 #define ppap pair<pa,int>
  #define PI 3.14159265358979323846
  #define paa pair<int,char>
  #define  mp make_pair
  #define  pb push_back
  #define EPS (1e-8)
                                          
    int dx[8]={0,1,0,-1,1,1,-1,-1};
    int dy[8]={1,0,-1,0,-1,1,1,-1};
                                            using namespace std;
                                   			class pa3{
                                            	public:
                                            	int x;
                                   				int y,z;
                                            	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                            	bool operator < (const pa3 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		 return z<p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                   				bool operator > (const pa3 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		 return z>p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa3 &p) const{
                                            		return x==p.x && y==p.y && z==p.z;
                                            	}
                                            		bool operator != (const pa3 &p) const{
                                            			return !( x==p.x && y==p.y && z==p.z);
                                            	}
                                            
                                            };
                                            
                                            class pa4{
                                            	public:
                                            	int x;
                                            	int y,z,w;
                                            	pa4(int x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                            	bool operator < (const pa4 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		if(z!=p.z)return z<p.z;
                                            		return w<p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator > (const pa4 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		if(z!=p.z)return z>p.z;
                                            		return w>p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa4 &p) const{
                                            		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                            	}
                                            		
                                            
                                            };
                                            class pa2{
                                            	public:
                                            	int x,y;
                                            	pa2(int x=0,int y=0):x(x),y(y) {}
                                            	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                            	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                            	bool operator < (const pa2 &p) const{
                                            		return y != p.y ? y<p.y: x<p.x;
                                            	}
                                            	bool operator > (const pa2 &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa2 &p) const{
                                            		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                            	}
                                            	bool operator != (const pa2 &p) const{
                                            		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                            	}
                                            		
                                            
                                            };
                                            
 
                      
                                string itos( int i ) {
                                ostringstream s ;
                                s << i ;
                                return s.str() ;
                                }
                                 
                                int gcd(int v,int b){
                                	if(v==0) return b;
                                	if(b==0) return v;
                                	if(v>b) return gcd(b,v);
                                	if(v==b) return b;
                                	if(b%v==0) return v;
                                	return gcd(v,b%v);
                                }
                 
                            
                                int mod;
int extgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int d = extgcd(b, a%b, y, x);
    y -= a/b * x;
    return d;
}
pa operator+(const pa & l,const pa & r) {   
    return {l.first+r.first,l.second+r.second};                                    
}    
pa operator-(const pa & l,const pa & r) {   
    return {l.first-r.first,l.second-r.second};                                    
}  
                                
                int pr[10000100];
                int inv[10000010];
                
                int beki(int wa,int rr,int warukazu){
                	if(rr==0) return 1%warukazu;
                	if(rr==1) return wa%warukazu;
                	wa%=warukazu;
                	if(rr%2==1) return ((ll)beki(wa,rr-1,warukazu)*(ll)wa)%warukazu;
                	ll zx=beki(wa,rr/2,warukazu);
                	return (zx*zx)%warukazu;
                }
 
                
    			int comb(int nn,int rr){
    				if(rr<0 || rr>nn || nn<0) return 0;
    				int r=pr[nn]*inv[rr];
    				r%=mod;
    				r*=inv[nn-rr];
    				r%=mod;
    				return r;
    			}
               
                void gya(int ert){
                	pr[0]=1;
                	for(int i=1;i<=ert;i++){
                		pr[i]=(pr[i-1]*i)%mod;
                	}
                		inv[ert]=beki(pr[ert],mod-2,mod);
                	for(int i=ert-1;i>=0;i--){
                		inv[i]=inv[i+1]*(i+1)%mod;
                	}
                }
                
              //   cin.tie(0);
    		//	ios::sync_with_stdio(false);
    			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
                 //sort(ve.begin(),ve.end(),greater<int>());
 //   mt19937(clock_per_sec);
  //  mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()) ;
      
       



int dp[2020][2020][2]={};


int l1,l2;
string s,t;
int solve(int x,int y,int d){
	if(dp[x][y][d]>=0) return dp[x][y][d];
	int p=0;
	if(d==0){
		if(x!=l1 && s[x]=='O')p=max(p,solve(x+1,y,1)+1);
		if(y!=l2 && t[y]=='O')p=max(p,solve(x,y+1,1)+1);
		
	}
	else{
		if(x!=l1 && s[x]=='I')p=max(p,solve(x+1,y,0)+1);
		if(y!=l2 && t[y]=='I')p=max(p,solve(x,y+1,0)+1);		
	}
	dp[x][y][d]=p;
	return p;
}

signed main(){
	
	
   cin.tie(0);
	ios::sync_with_stdio(false);

	//int l1,l2;
	cin>>l1>>l2;
	//string s,t;
	cin>>s>>t;
	
	for(int i=0;i<=l1;i++)for(int j=0;j<=l2;j++){
		dp[i][j][0]=-1;
		dp[i][j][1]=-1;
		
	}
	dp[l1][l2][0]=0;
	dp[l1][l2][1]=0;
	
	int ans=0;
	for(int i=0;i<=l1;i++)for(int j=0;j<=l2;j++){
		ans=max(ans,solve(i,j,1));
		solve(i,j,0);
	}
	
	if(ans>0 && ans%2==0)ans--;
	cout<<ans<<endl;
	
	return 0;
	

 
 }
accuracy: 1
time_ms: 110
memory_kb: 66536
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <iomanip>
#include <map>
#include <set>
#include <cmath>
#include <cstdio>
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define FOR(i,m,n) for(int (i)=(m);(i)<(n);(i)++)
#define All(v) (v).begin(),(v).end()
typedef long long ll;

int dp[2010][2010][2];

int main(){
    int M,N;
    cin >> M >> N;
    string S,T;
    cin >> S >> T;
    //dp[i][j][k]=Sのi文字目、Tのj文字目まで見て、列車の末尾がkの時に作れる最長の列車の長さ
    dp[0][0][0]=dp[0][0][1]=0;
    int res = 0;
    FOR(i,0,M+1){
        FOR(j,0,N+1){
            int tmp = 0;
            if(i>0)if(S[i-1]=='I')tmp = max(tmp,dp[i-1][j][0]+1);
            if(j>0)if(T[j-1]=='I')tmp = max(tmp,dp[i][j-1][0]+1);
            dp[i][j][1]=tmp;

            tmp = 0;
            if(i>0)if(S[i-1]=='O'&&dp[i-1][j][1]>0)tmp = max(tmp,dp[i-1][j][1]+1);
            if(j>0)if(T[j-1]=='O'&&dp[i][j-1][1]>0)tmp = max(tmp,dp[i][j-1][1]+1);
            dp[i][j][0]=tmp;      

            res = max(res,dp[i][j][1]);      
        }
    }
    cout << res << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 34616
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <iomanip>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = uint32_t;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template<class T> void chmin(T &a, const T &b){ a = (a < b ? a : b); }
template<class T> void chmax(T &a, const T &b){ a = (a > b ? a : b); }

int main() {
    int n, m;
    string s, t;
    cin >> n >> m >> s >> t;
    vector<vector<int>> dpi(n+1, vector<int>(m+1, 0));
    auto dpo = dpi;
    int ans = 0;
    for (int i = 0; i <= n; ++i) {
        for (int j = 0; j <= m; ++j) {
            if((i && s[i-1] == 'I') ) dpi[i][j] = 1;
            if((j && t[j-1] == 'I')) dpi[i][j] = 1;
            if(i && dpi[i-1][j] > 0 && s[i-1] == 'O') chmax(dpo[i][j], dpi[i-1][j]+1);
            if(i && dpo[i-1][j] > 0 && s[i-1] == 'I') chmax(dpi[i][j], dpo[i-1][j]+1);
            if(j && dpi[i][j-1] > 0 && t[j-1] == 'O') chmax(dpo[i][j], dpi[i][j-1]+1);
            if(j && dpo[i][j-1] > 0 && t[j-1] == 'I') chmax(dpi[i][j], dpo[i][j-1]+1);
            ans = max(ans, dpi[i][j]);
        }
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 34332
final_rank: 9