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

#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;

// Code size is too big,sorry.

class Loc {
public:
  Loc() {
    Table = new int[1001];
    for (int i = 0; i < 1001; i++) {
      Table[i] = -1;
    }
    index = 0;
  }
  void init_index() { index = 0; }
  void reg_loc(int location) { Table[index++] = location; }
  int next_loc() {
    int ret = Table[index];
    index++;
    return ret;
  }

private:
  int *Table;
  int index;
};

int H_lmt, W_lmt;
long long T_h, T_w, P_h, P_w;

int main() {

  scanf("%lld %lld", &T_h, &T_w);

  char T[T_h][T_w + 1];

  for (int i = 0; i < T_h; i++) {
    scanf("%s", T[i]);
  }

  scanf("%lld %lld", &P_h, &P_w);

  if ((T_h < P_h) || (T_w < P_w))
    return 0;

  char P[P_h][P_w + 1];

  for (int i = 0; i < P_h; i++) {
    scanf("%s", P[i]);
  }

  H_lmt = T_h - P_h, W_lmt = T_w - P_w;

  int P_count[128] = {0}, P_first_loc[128];

  for (int i = 0; i < 128; i++)
    P_first_loc[i] = -1;

  for (int row = 0; row < P_h; row++) {
    for (int col = 0; col < P_w; col++) {
      P_count[P[row][col]]++;
      if (P_first_loc[P[row][col]] == -1) {
        P_first_loc[P[row][col]] = 1000 * row + col;
      }
    }
  }
  int c_count = 0, c_min = 1000001, c_max = -1, min_char, max_char,
      appeard_min = 1000001;
  bool multFLG = false;
  for (int i = 48; i <= 122; i++) {
    if (P_count[i] > 0) {
      c_count++;
      if (c_min > P_count[i]) {
        c_min = P_count[i];
        min_char = i;
      }
      if (c_max < P_count[i]) {
        c_max = P_count[i];
        max_char = i;
      }
    }
    if (P_first_loc[i] != 0 && P_first_loc[i] < appeard_min) {
      appeard_min = P_first_loc[i];
    }
  }
  if (c_count >= 2)
    multFLG = true;

  int second_row = appeard_min / 1000, second_col = appeard_min % 1000,
      T_char_count[128] = {0};

  for (int row = 0; row < T_h; row++) {
    for (int col = 0; col < T_w; col++) {
      T_char_count[T[row][col]]++;
    }
  }
  int tc_count = 0, tc_max = -1, t_max_char;
  bool t_multFLG = false;
  for (int i = 48; i <= 122; i++) {
    if (T_char_count[i] > 0) {
      tc_count++;
      if (tc_max < T_char_count[i]) {
        tc_max = T_char_count[i];
        t_max_char = i;
      }
    }
  }
  if (tc_count >= 2)
    t_multFLG = true;

  for (int i = 0; i < 128; i++) {
    if (T_char_count[i] < P_count[i])
      return 0;
  }

  char p00 = P[0][0];
  if (multFLG == true) {
    if (c_max / (P_h * P_w - c_max) >= 899) {
      bool matchFLG;
      int chk_row = P_first_loc[min_char] / 1000,
          chk_col = P_first_loc[min_char] % 1000;

      for (int row = 0; row <= H_lmt; row++) {
        for (int col = 0; col <= W_lmt; col++) {
          if (T[row][col] == p00 &&
              T[row + chk_row][col + chk_col] == P[chk_row][chk_col]) {
            matchFLG = true;
            for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
              for (int tmp_col = 0; tmp_col < P_w; tmp_col++) {
                if (T[row + tmp_row][col + tmp_col] != P[tmp_row][tmp_col]) {
                  matchFLG = false;
                  break;
                }
              }
              if (!matchFLG)
                break;
            }
            if (matchFLG) {
              printf("%d %d\\n", row, col);
            }
          }
        }
      }
    } else if (P_w * second_row + second_col > 1000) {
      bool matchFLG;
      for (int row = 0; row <= H_lmt; row++) {
        for (int col = 0; col <= W_lmt; col++) {
          if (T[row][col] == p00 && T[row + second_row][col + second_col] ==
                                        P[second_row][second_col]) {
            matchFLG = true;
            for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
              for (int tmp_col = 0; tmp_col < P_w; tmp_col++) {
                if (T[row + tmp_row][col + tmp_col] != P[tmp_row][tmp_col]) {
                  matchFLG = false;
                  break;
                }
              }
              if (!matchFLG)
                break;
            }
            if (matchFLG) {
              printf("%d %d\\n", row, col);
            }
          }
        }
      }
    } else {
      bool ptnFLG = true;
      if ((100 * (c_max / P_h * P_w) <= 5) ||
          (100 * (tc_max / T_h * T_w) <= 5)) {
        ptnFLG = false;
      }
      if (ptnFLG) {
        if ((T_h - P_h) * (T_w - P_w) * (P_h * P_w) < 500000000) {
          ptnFLG = false;
        }
      }
      if (ptnFLG) {
        if (100 * abs(c_max / (P_h * P_w) - tc_max / (T_h * T_w)) >= 5) {
          ptnFLG = false;
        }
      }
      int second_p_max = -1, second_t_max = -1, second_p_char, second_t_char;
      if (ptnFLG) {
        for (int i = 0; i < 128; i++) {
          if (T_char_count[i] > 0 && i != t_max_char) {
            second_t_max = std::max(second_t_max, T_char_count[i]);
            second_t_char = i;
          }
          if (P_count[i] > 0 && i != max_char) {
            second_p_max = std::max(second_p_max, P_count[i]);
            second_p_char = i;
          }
        }
        if (100 *
                abs(second_p_max / (P_h * P_w) - second_t_max / (T_h * T_w)) >=
            2) {
          ptnFLG = false;
        }
      }
      if (ptnFLG) {
        if ((max_char != t_max_char && max_char != second_t_char) ||
            (second_p_char != t_max_char && second_p_char != second_t_char)) {
          ptnFLG = false;
        }
      }
      Loc p_brokenH, t_brokenH;
      bool yokoP = false, ptnP = false, lByokoP = false, lMyokoP = false,
           yokoT = false, ptnT = false, lByokoT = false, lMyokoT = false;
      int p_yoko_max_suc = 0, tmp_suc = 0, t_yoko_max_suc = 0;
      if (ptnFLG) {
        char tmp;
        for (int i = 0, k = 0; i < P_h; i++) {
          tmp = P[i][0];
          for (k = 1; k < P_w; k++) {
            if (tmp != P[i][k])
              break;
          }
          if (k != P_w) {
            p_yoko_max_suc = std::max(p_yoko_max_suc, tmp_suc);
            tmp_suc = 0;
            p_brokenH.reg_loc(1000 * i + k);
          } else {
            tmp_suc++;
          }
        }
        p_yoko_max_suc = std::max(p_yoko_max_suc, tmp_suc);

        if (100 * (p_yoko_max_suc / P_h) <= 5) {
          int **P_each_row_char = new int *[P_h];

          for (int i = 0; i < P_h; i++) {
            P_each_row_char[i] = new int[128];
            for (int k = 0; k < 128; k++) {
              P_each_row_char[i][k] = 0;
            }
            for (int k = 0; k < P_w; k++) {
              P_each_row_char[i][P[i][k]]++;
            }
          }
          int **P_dist_table = new int *[P_h];
          for (int i = 0; i < P_h; i++) {
            P_dist_table[i] = new int[128];
            for (int k = 0; k < 128; k++) {
              P_dist_table[i][k] = 0;
            }
          }
          int history_loc[128], tmp_dist, history_max, history_min;
          for (int i = 0; i < P_h; i++) {
            for (int k = 0; k < 128; k++)
              history_loc[k] = 0;
            for (int k = 0; k < P_w; k++) {
              if (history_loc[P[i][k]] == 0) {
                history_loc[P[i][k]] = k;
              } else {
                tmp_dist = k - history_loc[P[i][k]];
                history_max = P_dist_table[i][P[i][k]] / 1000;
                history_min = P_dist_table[i][P[i][k]] % 1000;
                if (history_max == 0 || history_max < tmp_dist) {
                  history_max = tmp_dist;
                }
                if (history_min == 0 || history_min > tmp_dist) {
                  history_min = tmp_dist;
                }
                P_dist_table[i][P[i][k]] = 1000 * history_max + history_min;
                history_loc[P[i][k]] = k;
              }
            }
          }
          bool val_and_count = true, char_dist = true;
          for (int i = 1, k = 0; i < P_h; i++) {
            for (k = 0; k < 128; k++) {
              if (P_each_row_char[i][k] != P_each_row_char[0][k] &&
                  abs(P_each_row_char[i][k] - P_each_row_char[0][k]) > 1) {
                val_and_count = false;
                break;
              }
            }
            if (k != 128)
              break;
          }
          bool Dist0 = true, DistOther = true;
          if (val_and_count) {
            int min_0 = 1001, max_0 = -1;
            for (int i = 0; i < 128; i++) {
              if (P_dist_table[0][i] > 0) {
                if (min_0 == 1001 && max_0 == -1) {
                  min_0 = P_dist_table[0][i] % 1000;
                  max_0 = P_dist_table[0][i] / 1000;
                  if (min_0 != max_0) {
                    Dist0 = false;
                    break;
                  }
                }
                if (min_0 != 1001 && max_0 != -1) {
                  if (P_dist_table[0][i] % 1000 != min_0 ||
                      P_dist_table[0][i] / 1000 != max_0) {
                    Dist0 = false;
                    break;
                  }
                }
              }
            }
          }
          if (Dist0) {
            for (int i = 1; i < P_h; i++) {
              for (int k = 0; k < 128; k++) {
                if (P_dist_table[0][k] != P_dist_table[i][k]) {
                  DistOther = false;
                  break;
                }
              }
            }
          }
          if (val_and_count == true && char_dist == true && Dist0 == true &&
              DistOther == true) {
            ptnP = true;
          }
        }
        if (100 * (p_yoko_max_suc / P_h) <= 5 && ptnP == false) {
          ptnFLG = false;
        } else {
          if (p_yoko_max_suc == P_h) {
            yokoP = true;
          } else if (100 * (p_yoko_max_suc / P_h) >= 50) {
            lByokoP = true;
          } else if (100 * (p_yoko_max_suc / P_h) >= 6) {
            lMyokoP = true;
          }
        }
        if (ptnFLG) {
          tmp_suc = 0;
          for (int i = 0, k = 0; i < T_h; i++) {
            tmp = T[i][0];
            for (k = 1; k < T_w; k++) {
              if (tmp != T[i][k])
                break;
            }
            if (k != T_w) {
              t_yoko_max_suc = std::max(t_yoko_max_suc, tmp_suc);
              tmp_suc = 0;
              t_brokenH.reg_loc(1000 * i + k);
            } else {
              tmp_suc++;
            }
          }
          t_yoko_max_suc = std::max(t_yoko_max_suc, tmp_suc);

          if (100 * (t_yoko_max_suc / T_h) <= 5) {
            int **T_each_row_char = new int *[T_h];
            for (int i = 0; i < T_h; i++) {
              T_each_row_char[i] = new int[128];
              for (int k = 0; k < 128; k++) {
                T_each_row_char[i][k] = 0;
              }
              for (int k = 0; k < T_w; k++) {
                T_each_row_char[i][T[i][k]]++;
              }
            }
            int **T_dist_table = new int *[T_h];
            for (int i = 0; i < T_h; i++) {
              T_dist_table[i] = new int[128];
              for (int k = 0; k < 128; k++) {
                T_dist_table[i][k] = 0;
              }
            }

            int history_loc[128], tmp_dist, history_max, history_min;
            for (int i = 0; i < T_h; i++) {
              for (int k = 0; k < 128; k++)
                history_loc[k] = 0;
              for (int k = 0; k < T_w; k++) {
                if (history_loc[T[i][k]] == 0) {
                  history_loc[T[i][k]] = k;
                } else {
                  tmp_dist = k - history_loc[T[i][k]];

                  history_max = T_dist_table[i][T[i][k]] / 1000;
                  history_min = T_dist_table[i][T[i][k]] % 1000;
                  if (history_max == 0 || history_max < tmp_dist) {
                    history_max = tmp_dist;
                  }
                  if (history_min == 0 || history_min > tmp_dist) {
                    history_min = tmp_dist;
                  }
                  T_dist_table[i][T[i][k]] = 1000 * history_max + history_min;
                  history_loc[T[i][k]] = k;
                }
              }
            }
            bool val_and_count = true;
            bool char_dist = true;
            for (int i = 1, k = 0; i < T_h; i++) {
              for (k = 0; k < 128; k++) {
                if (T_each_row_char[i][k] != T_each_row_char[0][k] &&
                    abs(T_each_row_char[i][k] - T_each_row_char[0][k]) > 1) {
                  val_and_count = false;
                  break;
                }
              }
              if (k != 128)
                break;
            }
            bool Dist0 = true;
            bool DistOther = true;
            if (val_and_count) {
              int min_0 = 1001, max_0 = -1;
              for (int i = 0; i < 128; i++) {
                if (T_dist_table[0][i] > 0) {
                  if (min_0 == 1001 && max_0 == -1) {
                    min_0 = T_dist_table[0][i] % 1000;
                    max_0 = T_dist_table[0][i] / 1000;
                    if (min_0 != max_0) {
                      Dist0 = false;
                      break;
                    }
                  }
                  if (min_0 != 1001 && max_0 != -1) {
                    if (T_dist_table[0][i] % 1000 != min_0 ||
                        T_dist_table[0][i] / 1000 != max_0) {
                      Dist0 = false;
                      break;
                    }
                  }
                }
              }
            }
            if (Dist0) {
              for (int i = 1; i < T_h; i++) {
                for (int k = 0; k < 128; k++) {
                  if (T_dist_table[0][k] != T_dist_table[i][k]) {
                    DistOther = false;
                    break;
                  }
                }
              }
            }

            if (val_and_count == true && char_dist == true && Dist0 == true &&
                DistOther == true) {
              ptnT = true;
            }
          }
          if (100 * (t_yoko_max_suc / T_h) <= 5 && ptnT == false) {
            ptnFLG = false;
          } else {
            if (t_yoko_max_suc == T_h) {
              yokoT = true;
            } else if (100 * (t_yoko_max_suc / T_h) >= 50) {
              lByokoT = true;
            } else if (100 * (t_yoko_max_suc / T_h) >= 6) {
              lMyokoT = true;
            }
          }
        }
      }

      if (ptnFLG) {
        if ((yokoP == true || lByokoP == true || lMyokoP == true) &&
            (yokoT == false && lByokoT == false && lMyokoT == false)) {
          ptnFLG = false;
        }
        if (ptnP == true && ptnT == false) {
          ptnFLG = false;
        }
      }

      if (ptnFLG) {
        if (yokoP == true) {

          if (yokoT == true && p_yoko_max_suc <= t_yoko_max_suc) {
            int yoko_top = 0, yoko_bottom = P_h - 1;
            int top_limit = T_h - P_h, search_row, out_W_lmt = T_w - P_w;

            while (yoko_top <= top_limit) {
              for (search_row = yoko_top; search_row <= yoko_bottom;
                   search_row++) {
                if (P[search_row - yoko_top][0] != T[search_row][0])
                  break;
              }

              if (search_row > yoko_bottom) {
                for (int out_col = 0; out_col <= out_W_lmt; out_col++) {
                  printf("%d %d\\n", yoko_top, out_col);
                }
              }
              yoko_top++;
              yoko_bottom++;
            }
          } else if ((lByokoT == true || lMyokoT == true) &&
                     p_yoko_max_suc <= t_yoko_max_suc) {
            int horizon_top = 0, horizon_bottom = P_h - 1;
            int top_limit = T_h - P_h, search_row, out_W_lmt = T_w - P_w,
                broken_row;

            while (horizon_top <= top_limit) {
              t_brokenH.init_index();
              for (search_row = horizon_top; search_row <= horizon_bottom;
                   search_row++) {
                if (P[search_row - horizon_top][0] != T[search_row][0])
                  break;
                while ((broken_row = t_brokenH.next_loc()) != -1) {
                  if (broken_row / 1000 == search_row) {
                    break;
                  }
                }
              }
              if (search_row > horizon_bottom) {
                for (int out_col = 0; out_col <= out_W_lmt; out_col++) {
                  printf("%d %d\\n", horizon_top, out_col);
                }
              }
              horizon_top++;
              horizon_bottom++;
            }
          }

        } else if (lByokoP == true) {
          if (yokoT == true) {
            // Do nothing
          } else if ((lByokoT == true || lMyokoT == true) &&
                     p_yoko_max_suc <= t_yoko_max_suc) {
            int horizon_top = 0, horizon_bottom = P_h - 1;
            int top_limit = T_h - P_h, search_row, out_W_lmt = T_w - P_w,
                broken_row;
            while (horizon_top <= top_limit) {
              t_brokenH.init_index();
              for (search_row = horizon_top; search_row <= horizon_bottom;
                   search_row++) {
                if (P[search_row - horizon_top][0] != T[search_row][0])
                  break;
                while ((broken_row = t_brokenH.next_loc()) != -1) {
                  if (broken_row / 1000 == search_row) {
                    break;
                  }
                }
              }
              if (search_row > horizon_bottom) {
                for (int out_col = 0; out_col <= out_W_lmt; out_col++) {
                  printf("%d %d\\n", horizon_top, out_col);
                }
              }
              horizon_top++;
              horizon_bottom++;
            }
          }
        } else if (lMyokoP == true) {
          if (yokoT == true) {
            // Do nothing
          } else if ((lByokoT == true || lMyokoT == true) &&
                     p_yoko_max_suc <= t_yoko_max_suc) {
            bool matchFLG;
            int broken_point, comp_count;
            for (int row = 0; row <= H_lmt; row++) {
              for (int col = 0; col <= W_lmt; col++) {
                if (T[row][col] == p00) {
                  t_brokenH.init_index();
                  comp_count = 0;
                  while ((broken_point = t_brokenH.next_loc()) != -1 &&
                         comp_count < 100) {
                    if (T[row + (broken_point / 1000)]
                         [col + (broken_point % 1000)] !=
                        P[broken_point / 1000][broken_point % 1000]) {
                      break;
                    }
                    comp_count++;
                  }
                  if (broken_point == -1 || comp_count == 100) {

                    bool leftMatchFLG = true;
                    for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
                      if (T[row + tmp_row][0] != P[tmp_row][0]) {
                        leftMatchFLG = false;
                        break;
                      }
                    }
                    if (leftMatchFLG) {
                      matchFLG = true;
                      for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
                        for (int tmp_col = 0; tmp_col < P_w; tmp_col++) {
                          if (T[row + tmp_row][col + tmp_col] !=
                              P[tmp_row][tmp_col]) {
                            matchFLG = false;
                            break;
                          }
                        }
                        if (!matchFLG)
                          break;
                      }
                      if (matchFLG) {
                        printf("%d %d\\n", row, col);
                      }
                    }
                  }
                }
              }
            }
          }
        } else if (ptnP) {
          bool matchFLG;
          for (int row = 0; row <= H_lmt; row++) {
            for (int col = 0; col <= W_lmt; col++) {
              if (T[row][col] == p00) {
                matchFLG = true;
                for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
                  if (T[row + tmp_row][col] != P[tmp_row][0]) {
                    matchFLG = false;
                    break;
                  }
                }
                if (matchFLG) {
                  printf("%d %d\\n", row, col);
                }
              }
            }
          }
        } else {
          // omit
        }
      } else {
        bool matchFLG;

        for (int row = 0; row <= H_lmt; row++) {
          for (int col = 0; col <= W_lmt; col++) {
            if (T[row][col] == p00) {
              matchFLG = true;
              for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
                for (int tmp_col = 0; tmp_col < P_w; tmp_col++) {
                  if (T[row + tmp_row][col + tmp_col] != P[tmp_row][tmp_col]) {
                    matchFLG = false;
                    break;
                  }
                }
                if (!matchFLG)
                  break;
              }
              if (matchFLG) {
                printf("%d %d\\n", row, col);
              }
            }
          }
        }
      }
    }

  } else if (P_h == 1 && P_w == 1) {
    char ch = P[0][0];
    for (int i = 0; i < T_h; i++) {
      for (int k = 0; k < T_w; k++) {
        if (T[i][k] == ch) {
          printf("%d %d\\n", i, k);
        }
      }
    }
  } else {
    if (t_multFLG) {
      if (max_char == p00 && ((tc_max) / (T_h * T_w - tc_max) >= 10000) &&
          (t_max_char == P[0][0])) {
        Loc tLoc;
        for (int row = 0; row < T_h; row++) {
          for (int col = 0; col < T_w; col++) {
            if (T[row][col] != t_max_char) {
              tLoc.reg_loc(1000 * row + col);
            }
          }
        }

        int **possibilityTable = new int *[T_h];
        for (int i = 0; i < T_h; i++) {
          possibilityTable[i] = new int[T_w];
          for (int k = 0; k < T_w; k++) {
            possibilityTable[i][k] = 0;
          }
        }
        tLoc.init_index();
        int del_loc = tLoc.next_loc();
        int del_left, del_right, del_top, del_floor, center_row, center_col;

        while (del_loc != -1) {
          center_row = del_loc / 1000;
          center_col = del_loc % 1000;

          if (0 < center_col - (P_w - 1)) {
            del_left = center_col - (P_w - 1);
          } else {
            del_left = 0;
          }
          del_right = center_col;
          if (0 < center_row - (P_h - 1)) {
            del_top = center_row - (P_h - 1);
          } else {
            del_top = 0;
          }
          del_floor = center_row;
          for (int i = del_top; i <= del_floor; i++) {
            for (int k = del_left; k <= del_right; k++) {
              possibilityTable[i][k] = -1;
            }
          }
          del_loc = tLoc.next_loc();
        }

        for (int row = 0; row <= H_lmt; row++) {
          for (int col = 0; col <= W_lmt; col++) {
            if (possibilityTable[row][col] == 0)
              printf("%d %d\\n", row, col);
          }
        }

      } else if (((T_h - P_h) * (T_w - P_w) * (P_h * P_w) < 500000000) ||
                 (tc_max / (T_h * T_w - tc_max) <= 1000)) {

        char p_ch = P[0][0];
        bool matchFLG;

        for (int row = 0; row <= H_lmt; row++) {
          for (int col = 0; col <= W_lmt; col++) {
            if (T[row][col] == p_ch) {
              matchFLG = true;
              for (int tmp_row = 0; tmp_row < P_h; tmp_row++) {
                for (int tmp_col = 0; tmp_col < P_w; tmp_col++) {
                  if (T[row + tmp_row][col + tmp_col] != P[tmp_row][tmp_col]) {
                    matchFLG = false;
                    break;
                  }
                }
                if (!matchFLG)
                  break;
              }
              if (matchFLG) {
                printf("%d %d\\n", row, col);
              }
            }
          }
        }
      } else {
        int S = 0, historyS;
        int top, bottom, left, right;
        int **calcTable = new int *[T_h];

        for (int i = 0; i < T_h; i++) {
          calcTable[i] = new int[T_w];
          for (int k = 0; k < T_w; k++) {
            if (T[i][k] != P[0][0]) {
              calcTable[i][k] = 1;
              if (i < P_h && k < P_w) {
                S++;
              }
            } else {
              calcTable[i][k] = 0;
            }
          }
        }
        if (S == 0)
          printf("0 0\\n");
        historyS = S;

        top = 0, left = 1, right = P_w, bottom = P_h - 1;

        while (top <= H_lmt) {
          while (right < T_w) {
            for (int row = top; row <= bottom; row++) {
              S -= calcTable[row][left - 1];
            }
            for (int row = top; row <= bottom; row++) {
              S += calcTable[row][right + 1];
            }
            if (S == 0) {
              printf("%d %d\\n", top, left);
            }
            left++;
            right++;
          }

          if (bottom < H_lmt) {
            for (int col = 0; col < T_w; col++) {
              historyS -= calcTable[top][col];
            }
            for (int col = 0; col < T_w; col++) {
              historyS += calcTable[bottom + 1][col];
            }

            if (historyS == 0) {
              printf("%d %d\\n", top + 1, 0);
            }
          }

          top++;
          bottom++;
          left = 1, right = P_w, S = historyS;
        }
      }

    } else {

      if (T[0][0] == P[0][0]) {

        for (int row = 0; row <= H_lmt; row++) {
          for (int col = 0; col <= W_lmt; col++) {
            printf("%d %d\\n", row, col);
          }
        }
      }
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <stdio.h>

using namespace std;

struct Node {
  int data;
  Node *prev;
  Node *next;
};

class List {
public:
  List() {
    motherNode = new Node();
    motherNode->data = -1;
    motherNode->prev = motherNode; //?????°?§?????????????
    motherNode->next = motherNode;
  };

  //??????????????????????????\\???????????±?????°??????????´¢???????????????
  void insertFromFirst(int x) {
    Node *tmpNode = motherNode->next;
    while (tmpNode != motherNode && tmpNode->data < x) {
      tmpNode = tmpNode->next;
    }

    if (tmpNode == motherNode) { //??????????????\\????????´???
      Node *tmpNode = motherNode->next;
      motherNode->next = new Node();
      motherNode->next->data = x;
      motherNode->next->prev = motherNode;
      motherNode->next->next = tmpNode;
      tmpNode->prev = motherNode->next;
    } else {
      while (tmpNode != motherNode && tmpNode->data < x) {
        tmpNode = tmpNode->next;
      }
      Node *prevNode = tmpNode->prev;
      tmpNode->prev = new Node();
      tmpNode->prev->data = x;
      tmpNode->prev->next = tmpNode;
      tmpNode->prev->prev = prevNode;
      prevNode->next = tmpNode->prev;
    }
  };
  void insertFromLast(int x) { //???????????§??°????????§????°??????????
    Node *tmpNode = motherNode->prev;
    if (tmpNode == motherNode) { //???????????????????????????????????´???
      motherNode->next = new Node();
      motherNode->next->data = x;
      motherNode->next->next = motherNode;
      motherNode->next->prev = motherNode;
      motherNode->prev = motherNode->next;
    } else { //??¢?????????????????????????????????????????¨????????´???
      while (tmpNode != motherNode && tmpNode->data > x) {
        tmpNode = tmpNode->prev;
      }
      Node *nextNode = tmpNode->next;
      tmpNode->next = new Node();
      tmpNode->next->data = x;
      tmpNode->next->next = nextNode;
      tmpNode->next->prev = tmpNode;
      nextNode->prev = tmpNode->next;
    }
  }

  void showList() {
    Node *tmpNode = motherNode->next;
    while (tmpNode != motherNode) {
      printf("%d %d\\n", tmpNode->data / 1000, tmpNode->data % 1000);
      tmpNode = tmpNode->next;
    }
  }

private:
  Node *motherNode;
};

class RangeTable {

public:
  RangeTable(int T_height, int T_width, int P_height, int P_width) {
    // ranges = new Range[166500];
    // range_index = 0;
    this->T_height = T_height;
    this->T_width = T_width;
    this->P_height = P_height;
    this->P_width = P_width;

    int row_limit = T_height - P_height, col_limit = T_width - P_width;
    check_table = new char
        *[T_height]; //??????????????????????????????????????¨?????????????????§???????????????????????¨
    for (int i = 0; i < T_height; i++) {
      check_table[i] = new char[T_width];

      //???????????´??????????????§???????????´????????????n???????????????
      for (int k = 0; k < T_width; k++) {
        if (i <= row_limit && k <= col_limit) {
          check_table[i][k] = 'o';
        } else {
          check_table[i][k] =
              'x'; //???????????´??????????????§???????????´?????????x???????????????
        }
      }
    }
  }

  //????????????
  void registerRange(int left_up, int right_down) {
    int row_start = left_up / 1000;  //??????????§???´???
    int row_end = right_down / 1000; //????????????
    int col_start = left_up % 1000;  //??????????§?
    int col_end = right_down % 1000; //????????????
    //?????????????????????????¨????<<??????????????£????????????>>??¬???????????????[??¬?????????????????¨??????]?????????????????????????´¢??????????????????????????????????????????????????????????????????????????¨???????????¨??????????????????????????????
    //??????????????????????????????????????????????????????????£?????????????????????´??????????????????????????????????¨??????°???????????¨????????????????????¬????????????????????????????????£?????????????????¨??????????????????????????????
    //???????????????????????¢??????????????§????????¬?????????????????§??????????????£????????????
    for (int i = row_start; i < row_end; i++) {
      for (int k = col_start; k < col_end; k++) {
        check_table[i][k] = 'r'; // registerd
      }
    }
  }

  int nextSearchLoc(int row, int col) {
    //????????¨??????????????????????????¨??????????????¬???????????????????????????????????????????????¬??????????§??????¨????????????????????????
    int row_limit = T_height - P_height, col_limit = T_width - P_width;

    for (int tmp_col = col; tmp_col <= col_limit;
         tmp_col++) { //????????????????????§??¢???
      if (check_table[row][tmp_col] == 'o') {
        return 1000 * row + tmp_col;
      }
    }
    for (int tmp_row = row + 1; row <= row_limit; row++) { //?¬?????????\\???
      for (int tmp_col = 0; tmp_col <= col_limit; tmp_col++) {
        if (check_table[tmp_row][tmp_col] == 'o') {
          return 1000 * tmp_row + tmp_col;
        }
      }
    }
    return -1; //??¨?????????range????????£?????´???
  }

private:
  char **check_table;
  // Range* ranges;
  int T_height, T_width, P_height, P_width;
};

int main() {

  int T_height, T_width, P_height, P_width;

  scanf("%d %d", &T_height, &T_width);

  char T[T_height][T_width + 1];

  for (int i = 0; i < T_height; i++) {
    scanf("%s", T[i]);
  }

  scanf("%d %d", &P_height, &P_width);

  if ((T_height < P_height) || (T_width < P_width))
    return 0; // T??????????????????????????????????°????????????°????´¢??????

  char P[P_height][P_width + 1];

  for (int i = 0; i < P_height; i++) {
    scanf("%s", P[i]);
  }

  // P????????????????¨??????????????????\\??????????????§?????????P???????????°?????°??????
  int P_total_char_count[128] = {0}, P_each_char_count[P_height][128],
      P_first_appeard_loc[128];
  for (int i = 0; i < 128; i++)
    P_first_appeard_loc[i] = -1;

  for (int i = 0; i < P_height; i++) {
    for (int k = 0; k < 128; k++)
      P_each_char_count[i][k] = 0;
  }

  for (int row = 0; row < P_height; row++) {
    for (int col = 0; col < P_width; col++) {
      P_total_char_count[P[row][col]]++;     //??¨??????????????°????¨????
      P_each_char_count[row][P[row][col]]++; //????????¨???????????°????¨????
      if (P_first_appeard_loc[P[row][col]] == -1) {
        P_first_appeard_loc[P[row][col]] =
            1000 * row + col; //?????????????????´??????????¨????
      }
    }
  }

  int c_count = 0, c_min = 10001, c_max = -1, min_char, max_char,
      second_appeard_loc, appeard_min = 10001;
  bool multFLG = false;
  for (int i = 48; i <= 122; i++) {
    if (P_total_char_count[i] > 0) {
      c_count++;
      if (c_min > P_total_char_count[i]) {
        c_min = P_total_char_count
            [i]; //????????????????°???????????????????????????°????¨????
        min_char = i; //?????????????????°????°?????????????????¨????
      }
      if (c_max < P_total_char_count[i]) {
        c_max = P_total_char_count
            [i];      //?????????????????????????????????????????°????¨????
        max_char = i; //?????????????????°???????????????????¨????
      }
    }
    if (P_first_appeard_loc[i] != 0 && P_first_appeard_loc[i] < appeard_min) {
      appeard_min =
          P_first_appeard_loc[i]; // 2??????????????????????????´???????????????
    }
  }
  if (c_count >= 2)
    multFLG = true;

  int second_appeard_row = appeard_min / 1000,
      second_appeard_col =
          appeard_min % 1000; // 2??????????????????????????´??????????¨????

  if ((multFLG == true) ||
      (P_height * P_width != 1 &&
       (P_height * P_width * 100 >
        T_height *
            T_width))) { //?????????????????????????¨????????????°????????????????????°1??§?????????????????¢????????§?????????????????´???

    char start_char = P[0][0];

    if (c_max / (P_height * P_width - c_max) >=
        1000) { //?????????????????§???????????£???????????´???

      int min_appeard_row = P_first_appeard_loc[min_char] / 1000,
          min_appeard_col = P_first_appeard_loc[min_char] % 1000;

      bool matchFLG;
      int row_limit = T_height - P_height, col_limit = T_width - P_width;
      // T???????????????????????°???????????¨????????°??????????????????????´¢???
      for (int row = 0; row <= row_limit; row++) {
        for (int col = 0; col <= col_limit; col++) {
          if (T[row][col] == start_char &&
              T[row + min_appeard_row][col + min_appeard_col] ==
                  P[min_appeard_row]
                   [min_appeard_col]) { //????????¨???????????????????????????????????§?????°?????????
            matchFLG = true;
            for (int tmp_row = 0; tmp_row < P_height;
                 tmp_row++) { //??????tmp_row,tmp_col?????????
              for (int tmp_col = 0; tmp_col < P_width; tmp_col++) {
                if (T[row + tmp_row][col + tmp_col] !=
                    P[tmp_row]
                     [tmp_col]) { //???????????????????????¨??????????????????????????´?????£?????´???
                  matchFLG = false;
                  break;
                }
              }
              if (!matchFLG)
                break;
            }
            if (matchFLG) {
              printf("%d %d\\n", row, col);
            }
          }
        }
      }
    } else if (
        P_width * second_appeard_row + second_appeard_col >
        1000) { //?????????????????§???????????£????????????????????????????????´????????????1000???????¶?????????´???

      bool matchFLG;
      int row_limit = T_height - P_height, col_limit = T_width - P_width;
      // T???????????????????????°???????????¨????????°??????????????????????´¢???
      for (int row = 0; row <= row_limit; row++) {
        for (int col = 0; col <= col_limit; col++) {
          if (T[row][col] == start_char &&
              T[row + second_appeard_row][col + second_appeard_col] ==
                  P[second_appeard_row]
                   [second_appeard_col]) { //????????¨???????????????????????????????????§?????°?????????
            matchFLG = true;
            for (int tmp_row = 0; tmp_row < P_height;
                 tmp_row++) { //??????tmp_row,tmp_col?????????
              for (int tmp_col = 0; tmp_col < P_width; tmp_col++) {
                if (T[row + tmp_row][col + tmp_col] !=
                    P[tmp_row]
                     [tmp_col]) { //???????????????????????¨??????????????????????????´?????£?????´???
                  matchFLG = false;
                  break;
                }
              }
              if (!matchFLG)
                break;
            }
            if (matchFLG) {
              printf("%d %d\\n", row, col);
            }
          }
        }
      }

    } else {
      bool matchFLG;
      int row_limit = T_height - P_height, col_limit = T_width - P_width;
      // T???????????????????????°???????????¨????????°??????????????????????´¢???
      for (int row = 0; row <= row_limit; row++) {
        for (int col = 0; col <= col_limit; col++) {
          if (T[row][col] ==
              start_char) { //????????¨???????????????????????????????????§?????°?????????
            matchFLG = true;
            for (int tmp_row = 0; tmp_row < P_height;
                 tmp_row++) { //??????tmp_row,tmp_col?????????
              for (int tmp_col = 0; tmp_col < P_width; tmp_col++) {
                if (T[row + tmp_row][col + tmp_col] !=
                    P[tmp_row]
                     [tmp_col]) { //???????????????????????¨??????????????????????????´?????£?????´???
                  matchFLG = false;
                  break;
                }
              }
              if (!matchFLG)
                break;
            }
            if (matchFLG) {
              printf("%d %d\\n", row, col);
            }
          }
        }
      }
    }

  } else if (P_height == 1 && P_width == 1) { // 1???????????´???
    char ch = P[0][0];
    for (int i = 0; i < T_height; i++) {
      for (int k = 0; k < T_width; k++) {
        if (T[i][k] == ch) {
          printf("%d %d\\n", i, k);
        }
      }
    }

  } else { //???????¨???????????????°???????????´???

    char ch = P[0][0]; //??¢?????????
    int location;

    RangeTable rangeTable(T_height, T_width, P_height, P_width);
    List list;

    location = rangeTable.nextSearchLoc(0, 0);

    int start_row, start_col, tmp_row, tmp_col, range_height, range_width,
        min_width = 0, min_height = 0;
    int calc_start_row, calc_start_col, calc_tmp_row, calc_tmp_col,
        calc_min_width = 0, calc_min_height = 0;
    if (P_height > P_width) { //???????????´???
      while (location != -1) {
        start_row = location / 1000, start_col = location % 1000;
        //?????????????????????????????±?????¨???????????????
        for (tmp_row = start_row; tmp_row < T_height; tmp_row++) {
          for (tmp_col = start_col; tmp_col < T_width; tmp_col++) {
            if (T[tmp_row][tmp_col] != ch) {
              if ((tmp_col - 1) - start_col >=
                  P_width) { //????????????????????????????????????????????????<tmp_col-1>:?????´??????????????????
                min_width = std::min(
                    min_width,
                    (tmp_col - 1) -
                        start_col); //????????????????????\\?????§???????????????range?????§???????°??????????<??¨???????????????????????????>????±???????
              }
              break;
            }
          }
          if ((tmp_col - 1) - start_col < P_width)
            break; //???????´¢???????????§?????´????????¨???<(tmp_row-1)-start_row>????????????????????????????????????range????´¢???????????£????????§break
        }
        if ((tmp_row - 1) - start_row >=
            P_height) { // range????????????????????§???list?????????
                        // <<?????¶????????????????????????????????????????????\\?????§????????¨???????????¨>>

          //?????¨???????????????????????????????????????
          range_height = (tmp_row - 1) - start_row; // range?????????
          range_width = min_width;                  // range??????
          rangeTable.registerRange(
              location,
              1000 * (start_row + range_height) +
                  (start_col +
                   range_width)); //??¬???????????????????????¬???????????????

          int calc_row_limit = start_row + range_height,
              calc_col_limit = start_col + range_width; //??¬??????????????????
          int secure_row_limit = calc_row_limit - P_height,
              secure_col_limit =
                  calc_col_limit -
                  P_width; //????????????????????????????????????????????\\???????¨??????????????????????????????¨???
          int danger_row_start = secure_row_limit + 1,
              danger_col_start =
                  secure_col_limit +
                  1; //??¨??????????£???????????????????range???????????????????????§???????????¨???
          int danger_row_end = calc_row_limit - 1,
              danger_col_end =
                  calc_col_limit -
                  1; //??±??????????????¨??????????????????????????????????????\\???range??¨??????????????????????????????????????§?????§????????????

          for (int calc_row = start_row; calc_row <= calc_row_limit;
               calc_row++) {
            for (int calc_col = start_col; calc_col <= calc_col_limit;
                 calc_col++) {
              if (calc_row <= secure_row_limit &&
                  calc_col <= secure_col_limit) { //?????¨???
                list.insertFromLast(1000 * calc_row + calc_col);
              } else if (calc_row >= danger_row_start &&
                         calc_row <= danger_row_end &&
                         calc_col >= danger_col_start &&
                         calc_col <= danger_col_end) { //??±?????????
                //?????????????§?????????????range??????????????????list?????????
                calc_start_row = calc_row, calc_start_col = calc_col;
                //?????????????????????????????±?????¨???????????????
                for (calc_tmp_row = calc_start_row; calc_tmp_row < T_height;
                     calc_tmp_row++) {
                  for (calc_tmp_col = calc_start_col; calc_tmp_col < T_width;
                       calc_tmp_col++) {
                    if (T[calc_tmp_row][calc_tmp_col] != ch) {
                      if ((calc_tmp_col - 1) - calc_start_col >=
                          P_width) { //????????????????????????????????????????????????<tmp_col-1>:?????´??????????????????
                        calc_min_width = std::min(
                            calc_min_width,
                            (calc_tmp_col - 1) -
                                calc_start_col); //????????????????????\\?????§???????????????range?????§???????°??????????<??¨???????????????????????????>????±???????
                      }
                      break;
                    }
                  }
                  if ((calc_tmp_col - 1) - calc_start_col < P_width)
                    break; //???????´¢???????????§?????´????????¨???????????????????????????????????????range????´¢???????????£????????§break
                }
                if ((calc_tmp_row - 1) - calc_start_row >=
                    P_height) { //??¨??????????£???????????????????range????????????????????§???list?????????
                  list.insertFromLast(1000 * calc_start_row + calc_start_col);
                }
              }
            }
          }
        }
        location = rangeTable.nextSearchLoc(
            location / 1000,
            location %
                1000); //?¬????range???????§?????????¨???????????????????§????
      }
    } else { //??£?????¢?????????????¨?????????´???
      while (location != -1) {
        start_row = location / 1000, start_col = location % 1000;
        //?????????????????????????????±?????¨???????????????
        for (tmp_col = start_col; tmp_col < T_width; tmp_col++) {
          for (tmp_row = start_row; tmp_row < T_height; tmp_row++) {
            if (T[tmp_row][tmp_col] != ch) {
              if ((tmp_row - 1) - start_row >=
                  P_height) { //???????????????????????????????????????????????????
                min_height = std::min(min_height, (tmp_row - 1) - start_row);
              }
              break;
            }
          }
          if ((tmp_row - 1) - start_row < P_height)
            break;
        }
        if ((tmp_col - 1) - start_col >= P_width) { // range????????????
          // rangeTable.registerRange(1000*start_row+start_col,1000*last_row+(tmp_col-1));
          //?????¨???????????????????????????????????????
          range_width = (tmp_col - 1) - start_col; // range??????
          range_height = min_height;               // range??????
          rangeTable.registerRange(location, 1000 * (start_row + range_height) +
                                                 (start_col + range_width));

          int calc_row_limit = start_row + range_height,
              calc_col_limit = start_col + range_width; //??¬??????????????????
          int secure_row_limit = calc_row_limit - P_height,
              secure_col_limit =
                  calc_col_limit -
                  P_width; //????????????????????????????????????????????\\???????¨??????????????????????????????¨???
          int danger_row_start = secure_row_limit + 1,
              danger_col_start =
                  secure_col_limit +
                  1; //??¨??????????£???????????????????range???????????????????????§???????????¨???
          int danger_row_end = calc_row_limit - 1,
              danger_col_end =
                  calc_col_limit -
                  1; //??±??????????????¨??????????????????????????????????????\\???range??¨??????????????????????????????????????§?????§????????????

          for (int calc_col = start_col; calc_col <= calc_col_limit;
               calc_col++) {
            for (int calc_row = start_row; calc_row <= calc_row_limit;
                 calc_row++) {
              if (calc_col <= secure_col_limit &&
                  calc_row <= secure_row_limit) { //?????¨???
                list.insertFromLast(1000 * calc_row + calc_col);
              } else if (calc_col >= danger_col_start &&
                         calc_col <= danger_col_end &&
                         calc_row >= danger_row_start &&
                         calc_row <= danger_row_end) { //??±?????????
                //?????????????§?????????????range??????????????????list?????????
                calc_start_col = calc_col, calc_start_row = calc_row;
                //?????????????????????????????±?????¨???????????????
                for (calc_tmp_col = calc_start_col; calc_tmp_col < T_width;
                     calc_tmp_col++) {
                  for (calc_tmp_row = calc_start_row; calc_tmp_row < T_height;
                       calc_tmp_row++) {
                    if (T[calc_tmp_row][calc_tmp_col] != ch) {
                      if ((calc_tmp_row - 1) - calc_start_row >= P_height) {
                        calc_min_height =
                            std::min(calc_min_height,
                                     (calc_tmp_row - 1) - calc_start_row);
                      }
                      break;
                    }
                  }
                  if ((calc_tmp_row - 1) - calc_start_row < P_height)
                    break; //???????????§?????´????????¨???????????????????????????????????????range????´¢???????????£????????§break
                }
                if ((calc_tmp_col - 1) - calc_start_col >=
                    P_width) { //??¨??????????£???????????????????range????????????????????§???list?????????
                  list.insertFromLast(1000 * calc_start_row + calc_start_col);
                }
              }
            }
          }
        }
        location = rangeTable.nextSearchLoc(
            location / 1000,
            location %
                1000); //?¬????range???????§?????????¨???????????????????§????
      }
    }

    list.showList();
  }

  return 0;
}