Problem p00971 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 4005

enum Type {
  type_A,
  type_B,
};

int dp[NUM][NUM];
int len_A, len_B;
int next_0[2][NUM], next_1[2][NUM];
char A[NUM], B[NUM];

int dfs(int loc_A, int loc_B) {

  if (loc_A == len_A && loc_B == len_B) {

    return 0;
  }

  if (dp[loc_A][loc_B] != -1) {

    return dp[loc_A][loc_B];
  }

  int min_length = BIG_NUM;
  int next_loc_A, next_loc_B;

  // 0
  if (loc_A >= len_A) {

    next_loc_A = len_A;
  } else {

    next_loc_A = next_0[type_A][loc_A];
  }

  if (loc_B >= len_B) {

    next_loc_B = len_B;
  } else {

    next_loc_B = next_0[type_B][loc_B];
  }

  min_length = min(min_length, dfs(next_loc_A, next_loc_B));

  // 1
  if (loc_A >= len_A) {

    next_loc_A = len_A;
  } else {

    next_loc_A = next_1[type_A][loc_A];
  }

  if (loc_B >= len_B) {

    next_loc_B = len_B;
  } else {

    next_loc_B = next_1[type_B][loc_B];
  }

  min_length = min(min_length, dfs(next_loc_A, next_loc_B));

  return dp[loc_A][loc_B] = min_length + 1;
}

void recursive(int loc_A, int loc_B) {

  if (loc_A >= len_A && loc_B >= len_B)
    return;

  if (dfs(min(len_A, next_0[type_A][loc_A]),
          min(len_B, next_0[type_B][loc_B])) +
          1 ==
      dfs(loc_A, loc_B)) {
    printf("0");
    recursive(min(len_A, next_0[type_A][loc_A]),
              min(len_B, next_0[type_B][loc_B]));
    return;
  }

  // 1
  if (dfs(min(len_A, next_1[type_A][loc_A]),
          min(len_B, next_1[type_B][loc_B])) +
          1 ==
      dfs(loc_A, loc_B)) {
    printf("1");
    recursive(min(len_A, next_1[type_A][loc_A]),
              min(len_B, next_1[type_B][loc_B]));
    return;
  }
}

int main() {

  scanf("%s", A);
  scanf("%s", B);

  for (len_A = 0; A[len_A] != '\\0'; len_A++)
    ;
  for (int i = len_A; i >= 1; i--) {
    A[i] = A[i - 1];
  }
  A[0] = '@';
  len_A++;

  for (len_B = 0; B[len_B] != '\\0'; len_B++)
    ;
  for (int i = len_B; i >= 1; i--) {

    B[i] = B[i - 1];
  }
  B[0] = '@';
  len_B++;

  for (int i = 0; i <= len_A; i++) {
    for (int k = 0; k <= len_B; k++) {

      dp[i][k] = -1;
    }
  }

  next_0[type_A][len_A] = len_A;
  next_1[type_A][len_A] = len_A;
  next_0[type_A][len_A - 1] = len_A;
  next_1[type_A][len_A - 1] = len_A;

  for (int loc = len_A - 2; loc >= 0; loc--) {

    if (A[loc + 1] == '0') {

      next_0[type_A][loc] = loc + 1;
      next_1[type_A][loc] = next_1[type_A][loc + 1];

    } else { // A[loc+1] == '1'

      next_0[type_A][loc] = next_0[type_A][loc + 1];
      next_1[type_A][loc] = loc + 1;
    }
  }

  next_0[type_B][len_B] = len_B;
  next_1[type_B][len_B] = len_B;
  next_0[type_B][len_B - 1] = len_B;
  next_1[type_B][len_B - 1] = len_B;

  for (int loc = len_B - 2; loc >= 0; loc--) {

    if (B[loc + 1] == '0') {

      next_0[type_B][loc] = loc + 1;
      next_1[type_B][loc] = next_1[type_B][loc + 1];

    } else { // B[loc+1] == '1'

      next_0[type_B][loc] = next_0[type_B][loc + 1];
      next_1[type_B][loc] = loc + 1;
    }
  }

  recursive(0, 0);
  printf("\\n");

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 4005

enum Type {
  type_A,
  type_B,
};

int dp[NUM][NUM]; // dp[最後の一致場所][最後の一致場所] = 最小インデックス
int len_A, len_B, len_ans;
int next_0[2][NUM], next_1[2][NUM];
char A[NUM], B[NUM];
char TMP[NUM], ans[NUM];

void recursive(int index, int loc_A, int loc_B) {

  if (loc_A == len_A && loc_B == len_B) { // A,Bともに非部分列となった場合

    if (index < len_ans) { // 過去最短

      len_ans = index;

      for (int i = 0; i < index; i++) {

        ans[i] = TMP[i];
      }
      ans[index] = '\\0';
      // printf("過去最短 ans:%s\\n",ans);

    } else if (index == len_ans) { // 長さが現最短長と同じ

      bool FLG = false;

      for (int i = 0; i < index; i++) {

        if (TMP[i] != ans[i]) {

          if (TMP[i] < ans[i]) {
            FLG = true;
          }
          break;
        }
      }

      if (FLG) {

        for (int i = 0; i < index; i++) {

          ans[i] = TMP[i];
        }
        // printf("最短更新 ans:%s\\n",ans);
      }
    }
    return;
  }

  if (index > 0 && index >= dp[loc_A][loc_B]) {
    // 過去最短長でなければreturn
    return;
  }
  if (index > 0) {

    dp[loc_A][loc_B] = index;
  }

  int next_loc_A, next_loc_B;
  // 0
  if (loc_A >= len_A) {

    next_loc_A = len_A;
  } else {

    next_loc_A = next_0[type_A][loc_A + 1];
  }

  if (loc_B >= len_B) {

    next_loc_B = len_B;
  } else {

    next_loc_B = next_0[type_B][loc_B + 1];
  }

  TMP[index] = '0';
  recursive(index + 1, next_loc_A, next_loc_B);

  // 1
  if (loc_A >= len_A) {

    next_loc_A = len_A;
  } else {

    next_loc_A = next_1[type_A][loc_A + 1];
  }

  if (loc_B >= len_B) {

    next_loc_B = len_B;
  } else {

    next_loc_B = next_1[type_B][loc_B + 1];
  }

  TMP[index] = '1';
  recursive(index + 1, next_loc_A, next_loc_B);
}

int main() {

  scanf("%s", A);
  scanf("%s", B);

  for (len_A = 0; A[len_A] != '\\0'; len_A++)
    ;
  for (len_B = 0; B[len_B] != '\\0'; len_B++)
    ;

  len_ans = BIG_NUM;

  for (int i = 0; i <= len_A; i++) {
    for (int k = 0; k <= len_B; k++) {

      dp[i][k] = BIG_NUM;
    }
  }

  // 次の場所を計算
  next_0[type_A][len_A] = len_A;
  next_1[type_A][len_A] = len_A;

  for (int loc = len_A - 1; loc >= 0; loc--) {

    if (A[loc] == '0') {

      next_0[type_A][loc] = loc;
      next_1[type_A][loc] = next_1[type_A][loc + 1];

    } else { // A[loc] == '1'

      next_0[type_A][loc] = next_0[type_A][loc + 1];
      next_1[type_A][loc] = loc;
    }
  }

  next_0[type_B][len_B] = len_B;
  next_1[type_B][len_B] = len_B;

  for (int loc = len_B - 1; loc >= 0; loc--) {

    if (B[loc] == '0') {

      next_0[type_B][loc] = loc;
      next_1[type_B][loc] = next_1[type_B][loc + 1];

    } else { // B[loc] == '1'

      next_0[type_B][loc] = next_0[type_B][loc + 1];
      next_1[type_B][loc] = loc;
    }
  }

  recursive(0, -1, -1);

  printf("%s\\n", ans);

  return 0;
}