Problem p00527 (C++)

Buggy submission (status: Runtime Error):

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <forward_list>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;
#define MFOR(i, end) for (size_t i = 0, end_##i = (end); i < end_##i; ++i)

size_t M, N;
char S[2500];
char T[2500];
enum class Mode_T : int8_t { none = 0, I, O };
int dp[2010][2010][3];
int func(int spos, int tpos, Mode_T last) {
  if (S[spos] == '\0' && T[tpos] == '\0') {
    return -2010 * 2010 * 3;
  }
  if (dp[spos][tpos][(int8_t)last] != -1) {
    return dp[spos][tpos][(int8_t)last];
  }
  int max = -2010 * 2010 * 3;
  if (last == Mode_T::none) {
    if (S[spos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos + 1, tpos, Mode_T::I)));
    }
    if (S[spos] != '\0')
      max = std::max(max, 0 + func(spos + 1, tpos, Mode_T::none));
    if (T[tpos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos, tpos + 1, Mode_T::I)));
    }
    if (T[tpos] != '\0')
      max = std::max(max, 0 + func(spos, tpos + 1, Mode_T::none));
  } else if (last == Mode_T::I) {
    if (S[spos] == 'O') {
      auto snpos = spos + 1;
      if (S[snpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(snpos + 1, tpos, Mode_T::I)));
      }
      if (T[tpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(snpos, tpos + 1, Mode_T::I)));
      }
    }
    if (T[tpos] == 'O') {
      auto tnpos = spos + 1;
      if (S[spos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(spos + 1, tnpos, Mode_T::I)));
      }
      if (T[tnpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(spos, tnpos + 1, Mode_T::I)));
      }
    }
  } else if (last == Mode_T::O) {
    assert(false);
    if (S[spos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos + 1, tpos, Mode_T::I)));
    }
    if (T[tpos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos, tpos + 1, Mode_T::I)));
    }
  }
  return dp[spos][tpos][(int8_t)last] = max;
}

int main() {
  for (auto &arr2 : dp)
    for (auto &arr1 : arr2)
      for (auto &i : arr1) {
        i = -1;
      }
  std::cin >> M >> N;
  std::cin >> S >> T;
  std::cout << std::max(0, func(0, 0, Mode_T::none)) << std::endl;
}

Fixed submission:

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <forward_list>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;
#define MFOR(i, end) for (size_t i = 0, end_##i = (end); i < end_##i; ++i)

size_t M, N;
char S[2500];
char T[2500];
enum class Mode_T : int8_t { none = 0, I, O };
int dp[2010][2010][3];
int func(int spos, int tpos, Mode_T last) {
  if (S[spos] == '\0' && T[tpos] == '\0') {
    return -2010 * 2010 * 3;
  }
  if (dp[spos][tpos][(int8_t)last] != -1) {
    return dp[spos][tpos][(int8_t)last];
  }
  int max = -2010 * 2010 * 3;
  if (last == Mode_T::none) {
    if (S[spos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos + 1, tpos, Mode_T::I)));
    }
    if (S[spos] != '\0')
      max = std::max(max, 0 + func(spos + 1, tpos, Mode_T::none));
    if (T[tpos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos, tpos + 1, Mode_T::I)));
    }
    if (T[tpos] != '\0')
      max = std::max(max, 0 + func(spos, tpos + 1, Mode_T::none));
  } else if (last == Mode_T::I) {
    if (S[spos] == 'O') {
      auto snpos = spos + 1;
      if (S[snpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(snpos + 1, tpos, Mode_T::I)));
      }
      if (T[tpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(snpos, tpos + 1, Mode_T::I)));
      }
    }
    if (T[tpos] == 'O') {
      auto tnpos = tpos + 1;
      if (S[spos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(spos + 1, tnpos, Mode_T::I)));
      }
      if (T[tnpos] == 'I') {
        max = std::max(max, 2 + std::max(0, func(spos, tnpos + 1, Mode_T::I)));
      }
    }
  } else if (last == Mode_T::O) {
    assert(false);
    if (S[spos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos + 1, tpos, Mode_T::I)));
    }
    if (T[tpos] == 'I') {
      max = std::max(max, 1 + std::max(0, func(spos, tpos + 1, Mode_T::I)));
    }
  }
  return dp[spos][tpos][(int8_t)last] = max;
}

int main() {
  for (auto &arr2 : dp)
    for (auto &arr1 : arr2)
      for (auto &i : arr1) {
        i = -1;
      }
  std::cin >> M >> N;
  std::cin >> S >> T;
  std::cout << std::max(0, func(0, 0, Mode_T::none)) << std::endl;
}