Problem p00527 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef double db;

#define fr first
#define sc second
#define pb push_back
#define rep(i, x) for (ll i = 0; i < x; i++)
#define rep1(i, x) for (ll i = 1; i <= x; i++)
#define rrep(i, x) for (ll i = x - 1; i >= 0; i--)
#define rrep1(i, x) for (ll i = x; i > 0; i--)

ll l1, l2;
string s1, s2;
ll dp[2000][2000]; // i,j???????????§?????????(I??????)

ll rec(ll x1, ll x2) {
  ll res = 1;
  if (dp[x1][x2] != -1)
    return dp[x1][x2];
  if (x1 == l1 && x2 == l2)
    return dp[x1][x2] = 0;
  if (x1 == l1) {
    if (x2 < l2 - 1 && s2[x2] == 'I' && s2[x2 + 1] == 'O')
      return dp[x1][x2] = rec(x1, x2 + 2) > 0 ? rec(x1, x2 + 2) + 2 : 1;
    else if (s2[x2] == 'I')
      return dp[x1][x2] = 1;
    else
      return dp[x1][x2] = 0;
  }
  if (x2 == l2) {
    if (x1 < l1 - 1 && s1[x1] == 'I' && s1[x1 + 1] == 'O')
      return dp[x1][x2] = rec(x1 + 2, x2) > 0 ? rec(x1 + 2, x2) + 2 : 1;
    else if (s1[x1] == 'I')
      return dp[x1][x2] = 1;
    else
      return dp[x1][x2] = 0;
  }
  if (s1[x1] == 'O' && s2[x2] == 'O')
    return dp[x1][x2] = 0;
  ll g;
  if ((s1[x1] == 'I' && s2[x2] == 'O') || (s1[x1] == 'O' && s2[x2] == 'I')) {
    g = rec(x1 + 1, x2 + 1);
    if (g > 0)
      res = max(res, g + 2);
  }
  if (x1 < l1 - 1 && s1[x1] == 'I' && s1[x1 + 1] == 'O') {
    g = rec(x1 + 2, x2);
    if (g > 0)
      res = max(res, g + 2);
  }
  if (x2 < l2 - 1 && s2[x2] == 'I' && s2[x2 + 1] == 'O') {
    g = rec(x1, x2 + 2);
    if (g > 0)
      res = max(res, g + 2);
  }
  return dp[x1][x2] = res;
}

int main() {
  ll ans = 0;
  memset(dp, -1, sizeof(dp));
  cin >> l1 >> l2;
  cin >> s1 >> s2;
  rrep(i, l1) {
    rrep(j, l2) { ans = max(ans, rec(i, j)); }
  }
  cout << ans << endl;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef double db;

#define fr first
#define sc second
#define pb push_back
#define rep(i, x) for (ll i = 0; i < x; i++)
#define rep1(i, x) for (ll i = 1; i <= x; i++)
#define rrep(i, x) for (ll i = x - 1; i >= 0; i--)
#define rrep1(i, x) for (ll i = x; i > 0; i--)

ll l1, l2;
string s1, s2;
ll dp[2001][2001]; // i,j???????????§?????????(I??????)

ll rec(ll x1, ll x2) {
  ll res = 1;
  if (dp[x1][x2] != -1)
    return dp[x1][x2];
  if (x1 == l1 && x2 == l2)
    return dp[x1][x2] = 0;
  if (x1 == l1) {
    if (x2 < l2 - 1 && s2[x2] == 'I' && s2[x2 + 1] == 'O')
      return dp[x1][x2] = rec(x1, x2 + 2) > 0 ? rec(x1, x2 + 2) + 2 : 1;
    else if (s2[x2] == 'I')
      return dp[x1][x2] = 1;
    else
      return dp[x1][x2] = 0;
  }
  if (x2 == l2) {
    if (x1 < l1 - 1 && s1[x1] == 'I' && s1[x1 + 1] == 'O')
      return dp[x1][x2] = rec(x1 + 2, x2) > 0 ? rec(x1 + 2, x2) + 2 : 1;
    else if (s1[x1] == 'I')
      return dp[x1][x2] = 1;
    else
      return dp[x1][x2] = 0;
  }
  if (s1[x1] == 'O' && s2[x2] == 'O')
    return dp[x1][x2] = 0;
  ll g;
  if ((s1[x1] == 'I' && s2[x2] == 'O') || (s1[x1] == 'O' && s2[x2] == 'I')) {
    g = rec(x1 + 1, x2 + 1);
    if (g > 0)
      res = max(res, g + 2);
  }
  if (x1 < l1 - 1 && s1[x1] == 'I' && s1[x1 + 1] == 'O') {
    g = rec(x1 + 2, x2);
    if (g > 0)
      res = max(res, g + 2);
  }
  if (x2 < l2 - 1 && s2[x2] == 'I' && s2[x2 + 1] == 'O') {
    g = rec(x1, x2 + 2);
    if (g > 0)
      res = max(res, g + 2);
  }
  return dp[x1][x2] = res;
}

int main() {
  ll ans = 0;
  memset(dp, -1, sizeof(dp));
  cin >> l1 >> l2;
  cin >> s1 >> s2;
  rrep(i, l1) {
    rrep(j, l2) { ans = max(ans, rec(i, j)); }
  }
  cout << ans << endl;
}