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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

int T_length, P_length, range;
int *Rank;
int *Suffix_Array;
int *Work;

char *T, *P;

enum Type {
  Big,
  Small,
};

struct RMQ {
  void set(int arg_minimum, int arg_maximum) {
    minimum = arg_minimum;
    maximum = arg_maximum;
  }
  int minimum, maximum;
};

int N = 1;
RMQ *Tree;

void init(int first_N) {
  while (N < first_N)
    N <<= 1;
}

void update(int index, int value) {

  index += N - 1;

  Tree[index].minimum = min(Tree[index].minimum, value);
  Tree[index].maximum = max(Tree[index].maximum, value);

  index = (index - 1) / 2;

  while (true) {

    Tree[index].minimum =
        min(Tree[2 * index + 1].minimum, Tree[2 * index + 2].minimum);
    Tree[index].maximum =
        max(Tree[2 * index + 1].maximum, Tree[2 * index + 2].maximum);

    if (index == 0)
      break;
    else {
      index = (index - 1) / 2;
    }
  }
}

ll find(int search_left, int search_right, int node_id, int node_left,
        int node_right, Type type) {

  if (search_right < node_left || search_left > node_right) {
    if (type == Small) {
      return BIG_NUM;
    } else { // type == Big
      return -1;
    }
  }

  if (search_left <= node_left && search_right >= node_right) {
    if (type == Small) {
      return Tree[node_id].minimum;
    } else {
      return Tree[node_id].maximum;
    }
  }

  if (type == Small) {
    ll left_min = find(search_left, search_right, 2 * node_id + 1, node_left,
                       (node_left + node_right) / 2, type);
    ll right_min = find(search_left, search_right, 2 * node_id + 2,
                        (node_left + node_right) / 2 + 1, node_right, type);

    return min(left_min, right_min);
  } else { // type == Big
    ll left_max = find(search_left, search_right, 2 * node_id + 1, node_left,
                       (node_left + node_right) / 2, type);
    ll right_max = find(search_left, search_right, 2 * node_id + 2,
                        (node_left + node_right) / 2 + 1, node_right, type);

    return max(left_max, right_max);
  }
}

int strCmp_Suffix_Array(int start) {
  int index, ret;

  ret = 0;

  for (index = 0; index < P_length && T[start + index] != '\\0'; index++) {
    if (P[index] != T[start + index]) {
      if (P[index] > T[start + index]) {
        ret = 2;
      } else {
        ret = 1;
      }
      break;
    }
  }
  if (ret == 0 && index < P_length) {
    ret = 2;
  }
  return ret;
}

int find_match_left() {

  int ret = BIG_NUM;

  int left = 0, right = T_length, m;
  m = (left + right) / 2;

  while (left <= right) {
    switch (strCmp_Suffix_Array(Suffix_Array[m])) {
    case 0:
      ret = min(ret, m);
      right = m - 1;
      break;
    case 1:
      right = m - 1;
      break;
    case 2:
      left = m + 1;
      break;
    }
    m = (left + right) / 2;
  }
  return ret;
}

int find_match_right() {

  int ret = -1;

  int left = 0, right = T_length, m;
  m = (left + right) / 2;

  while (left <= right) {
    switch (strCmp_Suffix_Array(Suffix_Array[m])) {
    case 0:
      ret = max(ret, m);
      left = m + 1;
      break;
    case 1:
      right = m - 1;
      break;
    case 2:
      left = m + 1;
      break;
    }
    m = (left + right) / 2;
  }
  return ret;
}

bool compare_Suffix_Array(int a, int b) {
  if (Rank[a] != Rank[b])
    return Rank[a] < Rank[b];
  else {
    int rank_a = a + range <= T_length ? Rank[a + range] : -1;
    int rank_b = b + range <= T_length ? Rank[b + range] : -1;
    return rank_a < rank_b;
  }
}

void make_Suffix_Array() {
  for (int i = 0; i <= T_length; i++) {
    Suffix_Array[i] = i;
    Rank[i] = i < T_length ? T[i] : -1;
  }

  for (range = 1; range <= T_length; range *= 2) {
    sort(Suffix_Array, Suffix_Array + (T_length + 1), compare_Suffix_Array);

    Work[Suffix_Array[0]] = 0;
    for (int i = 1; i <= T_length; i++) {
      Work[Suffix_Array[i]] =
          Work[Suffix_Array[i - 1]] +
          (compare_Suffix_Array(Suffix_Array[i - 1], Suffix_Array[i]) ? 1 : 0);
    }
    for (int i = 0; i <= T_length; i++) {
      Rank[i] = Work[i];
    }
  }
}

int main() {

  T = new char[2000001];
  scanf("%s", T);

  for (T_length = 0; T[T_length] != '\\0'; T_length++)
    ;
  Rank = new int[T_length + 1];
  Suffix_Array = new int[T_length + 1];
  Work = new int[T_length + 1];

  make_Suffix_Array();

  init(T_length);

  Tree = (RMQ *)malloc(sizeof(RMQ) * (2 * N));

  for (int i = 0; i <= 2 * N - 2; i++) {
    Tree[i].set(BIG_NUM, -1);
  }

  for (int i = 0; i <= T_length; i++) {
    update(i, Suffix_Array[i]);
  }

  P = new char[2000001];

  int M, match_left, match_right, most_left_index, most_right_index,
      first_P_length;

  scanf("%d", &M);

  for (int loop = 0; loop < M; loop++) {

    scanf("%s", P);
    for (P_length = 0; P[P_length] != '\\0'; P_length++)
      ;
    first_P_length = P_length;

    match_left = find_match_left();
    match_right = find_match_right();

    if (match_left != BIG_NUM) {
      most_left_index = find(match_left, match_right, 0, 0, N - 1, Small);
    }

    scanf("%s", P);
    for (P_length = 0; P[P_length] != '\\0'; P_length++)
      ;

    if (match_left == BIG_NUM) {
      printf("0\\n");
      continue;
    }

    match_left = find_match_left();
    match_right = find_match_right();

    if (match_left != BIG_NUM) {
      most_right_index = find(match_left, match_right, 0, 0, N - 1, Big);
      most_right_index = most_right_index + P_length - 1;
    } else {
      printf("0\\n");
      continue;
    }

    if (most_left_index > most_right_index ||
        most_left_index + first_P_length - 1 > most_right_index) {
      printf("0\\n");
    } else {
      printf("%d\\n", most_right_index - most_left_index + 1);
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>

using namespace std;

int T_char_count[128] = {0}, P_char_count[128];

class LocRecord {

public:
  LocRecord() {
    locationTable = new int *[128];
    for (int i = 48; i <= 57; i++) {
      if (T_char_count[i] > 0) {
        locationTable[i] = new int[T_char_count[i] + 1];
      }
    }
    for (int i = 65; i <= 90; i++) {
      if (T_char_count[i] > 0) {
        locationTable[i] = new int[T_char_count[i] + 1];
      }
    }
    for (int i = 97; i <= 122; i++) {
      if (T_char_count[i] > 0) {
        locationTable[i] = new int[T_char_count[i] + 1];
      }
    }
  }

  void init() {
    int limit;
    for (int i = 48; i <= 57; i++) {
      limit = T_char_count[i];
      if (T_char_count[i] > 0) {
        index[i] = 0;

        for (int k = 0; k <= limit; k++) {
          locationTable[i][k] = -1;
        }
      }
    }
    for (int i = 65; i <= 90; i++) {
      limit = T_char_count[i];
      if (T_char_count[i] > 0) {
        index[i] = 0;

        for (int k = 0; k <= limit; k++) {
          locationTable[i][k] = -1;
        }
      }
    }
    for (int i = 97; i <= 122; i++) {
      limit = T_char_count[i];
      if (T_char_count[i] > 0) {
        index[i] = 0;
        for (int k = 0; k <= limit; k++) {
          locationTable[i][k] = -1;
        }
      }
    }
  }

  void init_index() {
    for (int i = 48; i <= 57; i++) {
      index[i] = 0;
    }
    for (int i = 65; i <= 90; i++) {
      index[i] = 0;
    }
    for (int i = 97; i <= 122; i++) {
      index[i] = 0;
    }
  }

  void regist_loc(int ch, int location) {
    locationTable[ch][index[ch]] = location;
    index[ch]++;
  }

  int next_loc(int ch) {
    int ret = locationTable[ch][index[ch]];
    index[ch]++;
    return ret;
  }

private:
  int **locationTable;
  int index[128];
};

void compress(int compressed_array[], char base_array[], int &compressed_length,
              bool T_FLG) {

  int comp_index = 0, count = 0;
  char ch = base_array[0];
  for (int i = 0; base_array[i] != '\\0';) {

    if (ch == base_array[i]) {
      if (T_FLG) {
        T_char_count[ch]++;
      } else {
        P_char_count[ch]++;
      }
      count++;
      if (base_array[i + 1] == '\\0') {
        if (count >= 4) {
          compressed_array[comp_index - 2] = -1;
          compressed_array[comp_index - 1] = count;
        } else {
          compressed_array[comp_index++] = ch;
        }
      } else {
        if (count <= 3) {
          compressed_array[comp_index++] = ch;
        }
      }
      i++;
    } else {
      if (count >= 4) {
        compressed_array[comp_index - 2] = -1;
        compressed_array[comp_index - 1] = count;
      }
      count = 0;
      ch = base_array[i];
    }
  }
  compressed_length = comp_index;
}

int main() {
  int T_comp_index, P_comp_index, comp_P_length, comp_T_length, tmp, div_tmp;

  char *T = new char[200001];
  int *compressedT = new int[200001];

  char P[200001];
  int compressedP[200001];

  scanf("%s", T);

  compress(compressedT, T, comp_T_length, true);

  LocRecord loc_record;
  loc_record.init();

  loc_record.regist_loc(compressedT[0], 0);
  for (int i = 1; i < comp_T_length; i++) {
    if (compressedT[i] != -1 && compressedT[i - 1] != -1) {
      loc_record.regist_loc(compressedT[i], i);
    }
  }

  int *total_count = new int[comp_T_length];
  int sum = 0;
  for (int i = 0; i < comp_T_length; i++) {
    if ((i > 0 && compressedT[i - 1] != -1 && compressedT[i] != -1) || i == 0) {
      total_count[i] = sum;
      sum++;
    } else if (i > 0 && compressedT[i - 1] == -1) {
      sum += (compressedT[i] - 2);
      total_count[i] = sum;
      sum++;
    }
  }

  int n, left_start, right_end, left_length, right_length;
  bool zeroFLG, foundFLG;
  scanf("%d", &n);
  for (int loop_number = 0; loop_number < n; loop_number++) {

    left_start = -1, right_end = -1;
    for (int inner = 0; inner < 2; inner++) {
      zeroFLG = false;
      foundFLG = false;

      scanf("%s", P);
      if (inner == 0) {
        for (left_length = 0; P[left_length] != '\\0'; left_length++)
          ;
      } else {
        for (right_length = 0; P[right_length] != '\\0'; right_length++)
          ;
      }

      for (int i = 0; i < 128; i++)
        P_char_count[i] = 0;
      compress(compressedP, P, comp_P_length, false);

      for (int i = 0; i < 128; i++) {
        if (T_char_count[i] < P_char_count[i]) {
          zeroFLG = true;
          break;
        }
      }
      if (zeroFLG)
        continue;

      bool multFLG = false, leftsuceedFLG = false, rightsucceedFLG = false;
      int most_left = compressedP[0], most_right = compressedP[0];
      for (int i = 1; i < comp_P_length; i++) {
        if (compressedP[i - 1] != -1 && compressedP[i] != -1) {
          most_right = compressedP[i];
          if (compressedP[i] != most_left) {
            multFLG = true;
          }
        }
      }

      if (comp_P_length > 2 && compressedP[comp_P_length - 2] == -1) {
        rightsucceedFLG = true;
      }

      if (comp_P_length > 1 && compressedP[1] == -1)
        leftsuceedFLG = true;

      if (multFLG) {

        loc_record.init_index();
        T_comp_index = loc_record.next_loc(most_right);

        /*if(T_comp_index == -1){
                continue;
        }*/

        int outputFLG;

        while (T_comp_index != -1 && T_comp_index < comp_T_length) {
          tmp = T_comp_index;
          P_comp_index = comp_P_length - 1;
          outputFLG = 0;
          while (P_comp_index >= 0 && tmp >= 0) {

            if (tmp == T_comp_index) {
              if (rightsucceedFLG) {
                if ((tmp < comp_T_length - 2) && (compressedT[tmp + 1] == -1) &&
                    (compressedT[tmp + 2] >= compressedP[comp_P_length - 1])) {
                  tmp -= 1;
                  P_comp_index -= 3;
                } else {
                  break;
                }
              } else {
                if ((tmp < comp_T_length - 2) && (compressedT[tmp + 1] == -1)) {
                  if (compressedP[P_comp_index] !=
                      compressedP[P_comp_index - 1]) {
                    tmp--;
                    P_comp_index--;
                  } else if ((compressedP[P_comp_index] ==
                              compressedP[P_comp_index - 1]) &&
                             (compressedP[P_comp_index - 1] !=
                              compressedP[P_comp_index - 2])) {
                    tmp--;
                    P_comp_index -= 2;
                  } else {
                    tmp--;
                    P_comp_index -= 3;
                  }
                } else {
                  tmp--;
                  P_comp_index--;
                }
              }
            } else if (leftsuceedFLG && P_comp_index == 2) {
              if ((tmp > 1) && (compressedT[tmp - 1] == -1) &&
                  (compressedT[tmp] >= compressedP[P_comp_index]) &&
                  compressedT[tmp - 2] == compressedP[0]) {
                tmp -= 3;
                P_comp_index -= 3;
                outputFLG = 2;
              } else {
                break;
              }
            } else if ((leftsuceedFLG == false) && (P_comp_index == 2) &&
                       (compressedP[2] == compressedP[1]) &&
                       (compressedP[1] == compressedP[0])) {

              if ((tmp >= 2) && (compressedT[tmp - 1] == -1) &&
                  (compressedT[tmp - 2] == compressedP[0])) {
                tmp -= 3;
                P_comp_index -= 3;
                outputFLG = 3;
              } else if (compressedP[P_comp_index] == compressedT[tmp] &&
                         tmp > 1 && compressedT[tmp] == compressedT[tmp - 1] &&
                         compressedT[tmp - 1] == compressedT[tmp - 2]) {
                tmp -= 3;
                P_comp_index -= 3;

              } else {
                break;
              }

            } else if ((leftsuceedFLG == false) && (P_comp_index == 1) &&
                       (compressedP[1] == compressedP[0])) {

              if ((tmp >= 2) && (compressedT[tmp - 1] == -1) &&
                  (compressedT[tmp - 2] == compressedP[0])) {
                tmp -= 3;
                P_comp_index -= 2;
                outputFLG = 3;
              } else if ((compressedP[P_comp_index] == compressedT[tmp]) &&
                         (tmp > 0) && (compressedT[tmp - 1] != -1) &&
                         (compressedT[tmp - 2] != -1) &&
                         (compressedT[tmp] == compressedT[tmp - 1])) {
                tmp -= 2;
                P_comp_index -= 2;
              } else if ((compressedP[P_comp_index] == compressedT[tmp]) &&
                         (tmp == 1) &&
                         (compressedT[tmp] == compressedT[tmp - 1])) {
                tmp -= 2;
                P_comp_index -= 2;
              } else {
                break;
              }

            } else if ((leftsuceedFLG == false) && (P_comp_index == 0) &&
                       (tmp >= 2) && (compressedT[tmp - 1] == -1) &&
                       (compressedT[tmp - 2] == compressedP[P_comp_index])) {
              tmp -= 3;
              P_comp_index--;
              outputFLG = 3;
            } else {
              if (compressedP[P_comp_index] == compressedT[tmp]) {
                tmp -= 1;
                P_comp_index--;
              } else {
                break;
              }
            }
          }

          if (P_comp_index == -1) {
            switch (outputFLG) {
            case 0:
              if (inner == 0) {
                left_start = total_count[tmp + 1];
                foundFLG = true;
              } else {
                right_end = total_count[tmp + 1];
              }

              break;
            case 2:
              if (inner == 0) {
                left_start = total_count[tmp + 1] + compressedT[tmp + 3] -
                             compressedP[2];
                foundFLG = true;
              } else {
                right_end = total_count[tmp + 1] + compressedT[tmp + 3] -
                            compressedP[2];
              }
              break;
            case 3:
              if (compressedP[0] != compressedP[1]) {
                if (inner == 0) {
                  left_start = total_count[tmp + 1] + compressedT[tmp + 3] - 1;
                  foundFLG = true;
                } else {
                  right_end = total_count[tmp + 1] + compressedT[tmp + 3] - 1;
                }
              } else if (compressedP[0] == compressedP[1] &&
                         compressedP[0] != compressedP[2]) {
                if (inner == 0) {
                  left_start = total_count[tmp + 1] + compressedT[tmp + 3] - 2;
                  foundFLG = true;
                } else {
                  right_end = total_count[tmp + 1] + compressedT[tmp + 3] - 2;
                }
              } else {
                if (inner == 0) {
                  left_start = total_count[tmp + 1] + compressedT[tmp + 3] - 3;
                  foundFLG = true;
                } else {
                  right_end = total_count[tmp + 1] + compressedT[tmp + 3] - 3;
                }
              }
              break;
            }
          }

          if (inner == 0 && foundFLG == true)
            break;

          div_tmp = loc_record.next_loc(most_right);
          if (div_tmp == -1) {
            break;
          } else {
            T_comp_index = div_tmp;
          }
        }

      } else {
        loc_record.init_index();
        int start = loc_record.next_loc(most_right);

        if (start == -1) {
          continue;
        }

        if (rightsucceedFLG) {
          for (int i = start; i < comp_T_length;) {
            if (i < comp_T_length - 2 && compressedT[i + 1] == -1 &&
                compressedT[i + 2] >= compressedP[comp_P_length - 1]) {
              int t_s = compressedT[i + 2];
              int p_s = compressedP[comp_P_length - 1];
              if (inner == 0) {
                left_start = total_count[i];
                break;
              } else {

                for (int k = 0; p_s + k <= t_s; k++) {
                  right_end = total_count[i] + k;
                }
              }
            }
            while (true) {
              i = loc_record.next_loc(most_right);
              if (i == -1) {
                zeroFLG = true;
                break;
              } else {
                if (compressedT[i] == most_right && i < comp_T_length - 2 &&
                    compressedT[i + 1] == -1 &&
                    compressedT[i + 2] >= compressedP[comp_P_length - 1]) {
                  break;
                }
              }
            }
            if (zeroFLG)
              break;
          }

        } else {
          for (int i = start; i < comp_T_length;) {
            if (i < comp_T_length - 2 && compressedT[i + 1] == -1) {
              int t_s = compressedT[i + 2];
              int p_s = comp_P_length;

              if (inner == 0) {
                left_start = total_count[i];
                break;
              } else {

                for (int k = 0; p_s + k <= t_s; k++) {
                  right_end = total_count[i] + k;
                }
              }
            } else {
              if (comp_P_length == 1) {
                if (inner == 0) {
                  left_start = total_count[i];
                  break;
                } else {
                  right_end = total_count[i];
                }

              } else if (comp_P_length == 2 && i < comp_T_length - 1 &&
                         compressedT[i + 1] == most_right) {
                if (inner == 0) {
                  left_start = total_count[i];
                  break;
                } else {
                  right_end = total_count[i];
                }
              } else if (comp_P_length == 3 && i < comp_T_length - 2 &&
                         compressedT[i + 1] == most_right &&
                         compressedT[i + 2] == most_right) {
                if (inner == 0) {
                  left_start = total_count[i];
                  break;
                } else {
                  right_end = total_count[i];
                }
              }
            }
            while (true) {
              i = loc_record.next_loc(most_right);
              if (i == -1) {
                zeroFLG = true;
                break;
              } else {
                break;
              }
            }
            if (zeroFLG)
              break;
          }
        }
      }
    }
    if (left_start == -1 || right_end == -1) {
      printf("0\\n");
    } else if (left_start > right_end) {
      printf("0\\n");
    } else if (left_start + left_length - 1 > right_end + right_length - 1) {
      printf("0\\n");
    } else {
      printf("%d\\n", (right_end + right_length - 1 - left_start + 1));
    }
  }

  return 0;
}