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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#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;

struct Info {
  char name[21];
  int length;
};

int POW[21];
int N, num_line, TEXT_LENGTH;
char buf[101], TEXT[5001];
bool is_match[5001], pattern_match[5001][20];
Info info[20];
map<int, bool> MAP;

void recursive(int start_loc, int loc, int state) {
  if (is_match[start_loc])
    return; // すくなくとも1つがマッチしたならreturn

  if (state == POW[N] - 1) { // 全文字一致
    is_match[start_loc] = true;
    return;
  }

  int next_state, next_loc;

  for (int loop = 0; loop < N; loop++) {
    if (state & (1 << loop)) { // 使用済
      // Do nothin
    } else { // TEXT[loc]から、info[loop]との一致比較
      if (pattern_match[loc][loop]) {
        next_state = state + POW[loop];
        auto at = MAP.find(next_state);
        if (at != MAP.end())
          continue;
        MAP[next_state] = true;
        next_loc = loc + info[loop].length;
        recursive(start_loc, next_loc, next_state);
      }
    }
  }
}

void func() {

  int length, sum_length = 0;

  for (int i = 0; i < N; i++) {
    scanf("%s", info[i].name);
    for (length = 0; info[i].name[length] != '\\0'; length++)
      ;
    info[i].length = length;
    sum_length += length;
  }

  // テキストの読み込み
  int index = 0;
  for (int loop = 0; loop < num_line; loop++) {
    scanf("%s", buf);
    for (int k = 0; buf[k] != '\\n' && buf[k] != '\\0'; k++) {
      TEXT[index++] = buf[k];
    }
  }
  TEXT_LENGTH = index;

  for (int i = 0; i < TEXT_LENGTH; i++)
    is_match[i] = false;

  bool FLG;
  // 場所と文字の一致を先に計算しておく
  for (int loc = 0; loc < TEXT_LENGTH; loc++) {
    for (int i = 0; i < N; i++)
      pattern_match[loc][i] = false;
  }

  for (int loc = 0; loc < TEXT_LENGTH; loc++) {
    for (int i = 0; i < N; i++) {
      if (loc + info[i].length > TEXT_LENGTH)
        continue;
      FLG = true;
      for (int k = 0; k < info[i].length; k++) {
        if (TEXT[loc + k] != info[i].name[k]) {
          FLG = false;
          break;
        }
      }
      if (FLG)
        pattern_match[loc][i] = true;
    }
  }

  // 一致の先頭となりえる箇所を全探索
  for (int start_loc = 0; start_loc <= TEXT_LENGTH - sum_length; start_loc++) {
    MAP.clear();
    recursive(start_loc, start_loc, 0);
  }

  int ans = 0;
  for (int i = 0; i < TEXT_LENGTH; i++) {
    if (is_match[i])
      ans++;
  }

  printf("%d\\n", ans);
}

int main() {

  for (int i = 0; i < 21; i++)
    POW[i] = pow(2, i);

  while (true) {
    scanf("%d %d", &N, &num_line);
    if (N == 0 && num_line == 0)
      break;

    func();
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#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;

struct Info {
  char name[21];
  int length;
};

int POW[21];
int N, num_line, TEXT_LENGTH;
char buf[101], TEXT[5001];
bool is_match[5001], pattern_match[5001][20];
Info info[20];

void recursive(int start_loc, int loc, int state) {
  if (is_match[start_loc])
    return; // すくなくとも1つがマッチしたならreturn

  if (state == POW[N] - 1) { // 全文字一致
    is_match[start_loc] = true;
    return;
  }

  int next_state, next_loc;

  for (int loop = 0; loop < N; loop++) {
    if (state & (1 << loop)) { // 使用済
      // Do nothin
    } else { // TEXT[loc]から、info[loop]との一致比較
      if (pattern_match[loc][loop]) {
        next_state = state + POW[loop];
        next_loc = loc + info[loop].length;
        recursive(start_loc, next_loc, next_state);
      }
    }
  }
}

void func() {

  int length, sum_length = 0;

  for (int i = 0; i < N; i++) {
    scanf("%s", info[i].name);
    for (length = 0; info[i].name[length] != '\\0'; length++)
      ;
    info[i].length = length;
    sum_length += length;
  }

  // テキストの読み込み
  int index = 0;
  for (int loop = 0; loop < num_line; loop++) {
    scanf("%s", buf);
    for (int k = 0; buf[k] != '\\n' && buf[k] != '\\0'; k++) {
      TEXT[index++] = buf[k];
    }
  }
  TEXT_LENGTH = index;

  for (int i = 0; i < TEXT_LENGTH; i++)
    is_match[i] = false;

  bool FLG;
  // 場所と文字の一致を先に計算しておく
  for (int loc = 0; loc < TEXT_LENGTH; loc++) {
    for (int i = 0; i < N; i++)
      pattern_match[loc][i] = false;
  }

  for (int loc = 0; loc < TEXT_LENGTH; loc++) {
    for (int i = 0; i < N; i++) {
      if (loc + info[i].length > TEXT_LENGTH)
        continue;
      FLG = true;
      for (int k = 0; k < info[i].length; k++) {
        if (TEXT[loc + k] != info[i].name[k]) {
          FLG = false;
          break;
        }
      }
      if (FLG)
        pattern_match[loc][i] = true;
    }
  }

  // 一致の先頭となりえる箇所を全探索
  for (int start_loc = 0; start_loc <= TEXT_LENGTH - sum_length; start_loc++) {
    recursive(start_loc, start_loc, 0);
  }

  int ans = 0;
  for (int i = 0; i < TEXT_LENGTH; i++) {
    if (is_match[i])
      ans++;
  }

  printf("%d\\n", ans);
}

int main() {

  for (int i = 0; i < 21; i++)
    POW[i] = pow(2, i);

  while (true) {
    scanf("%d %d", &N, &num_line);
    if (N == 0 && num_line == 0)
      break;

    func();
  }

  return 0;
}