Problem p04042 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#define cmax(a, b) (a < (b) ? a = (b), 1 : 0)
#define cmin(a, b) (a > (b) ? a = (b), 1 : 0)
#define dmin(a, b) ((a) < (b) ? (a) : (b))
#define dmax(a, b) ((a) > (b) ? (a) : (b))
#define regsiter register
#define CL fclose(stdin), fclose(stdout)
namespace io {
int F() {
  int n = 0, F = 1;
  char ch;
  while ((ch = getchar()) != '-' && (ch < '0' || ch > '9'))
    ;
  ch == '-' ? F = 0 : n = ch - '0';
  while ((ch = getchar()) >= '0' && ch <= '9')
    n = (n << 1) + (n << 3) + ch - '0';
  return F ? n : -n;
}
long long G() {
  long long n = 0, F = 1;
  char ch;
  while ((ch = getchar()) != '-' && (ch < '0' || ch > '9'))
    ;
  ch == '-' ? F = 0 : n = ch - '0';
  while ((ch = getchar()) >= '0' && ch <= '9')
    n = (n << 1) + (n << 3) + ch - '0';
  return F ? n : -n;
}
} // namespace io
#include <cassert>
const int S = 4000039;
const int M = 998244353;
bool c[2011][10011];
bool f[2011][10011];
char g[10011];
int h[10011];
char s[2011][10011];
int len[2011];
int ex[10011];
int max;
int slcp[10011];
int lcp[10011];
int cmp(int i, int j, int min, int &ans) {
  int l1 = lcp[j + 1];
  if (l1 < min - j) {
    ans = j + l1;
    if (l1 == len[i])
      return 0;
    if (s[i][l1 + 1] < g[j + l1 + 1])
      return -1;
    return 1;
  }
  if (j + len[i] == min)
    return 0;
  int l2 = slcp[min - j + 1];
  ans = min + l2;
  if (min + l2 == j + len[i])
    return 0;
  if (s[i][l2 + 1] > s[i][min - j + l2 + 1])
    return -1;
  return 1;
}
int main() {
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
  int n = io::F(), k = io::F();
  ex[0] = 1;
  for (register int i = 1; i <= k; ++i)
    ex[i] = (ex[i - 1] * (long long)S) % M;
  for (register int i = 1; i <= n; ++i)
    scanf("%s", s[i] + 1), len[i] = strlen(s[i] + 1);
  c[n + 1][0] = 1;
  for (register int i = n; i; --i)
    for (register int j = 0; j <= k; ++j) {
      c[i][j] = c[i + 1][j];
      if (j >= len[i])
        c[i][j] |= c[i + 1][j - len[i]];
    }
  f[0][0] = 1;
  for (register int i = 1; i <= n; ++i) {
    int min = -1;
    slcp[1] = len[i];
    int la = 0;
    for (register int j = 2; j <= len[i]; ++j) {
      if (j < la + slcp[la]) {
        int t = j - la + 1;
        if (t + slcp[t] - 1 < slcp[la])
          slcp[j] = slcp[t];
        else
          for (slcp[j] = la + slcp[la] - j, la = j;
               s[i][j + slcp[j]] == s[i][1 + slcp[j]]; ++slcp[j])
            ;
      } else {
        for (slcp[j] = 0; s[i][j + slcp[j]] == s[i][1 + slcp[j]]; ++slcp[j])
          ;
        la = j;
      }
    }
    la = 0;
    for (register int j = 1; j <= max; ++j) {
      if (j < la + lcp[la]) {
        int t = j - la + 1;
        if (t + slcp[t] - 1 < lcp[la])
          lcp[j] = slcp[t];
        else
          for (lcp[j] = la + lcp[la] - j, la = j;
               1 + lcp[j] <= len[i] && j + lcp[j] <= max &&
               s[i][1 + lcp[j]] == g[j + lcp[j]];
               ++lcp[j])
            ;
      } else {
        for (lcp[j] = 0; 1 + lcp[j] <= len[i] && j + lcp[j] <= max &&
                         s[i][1 + lcp[j]] == g[j + lcp[j]];
             ++lcp[j])
          ;
        la = j;
      }
    }
    int ml = max;
    for (register int j = max; j >= 0; --j)
      if (j + len[i] <= k && c[i + 1][k - j - len[i]] && f[i - 1][j])
        if (min == -1) {
          int l1 = lcp[j + 1];
          if (j == max || j + l1 == dmin(max, j + len[i]) ||
              s[i][l1 + 1] < g[j + l1 + 1])
            min = j, ml = j + l1;
        } else {
          int L;
          int tmp = cmp(i, j, min, L);
          if (tmp == -1) {
            min = j;
            ml = L;
          }
        }
    if (min != -1) {
      for (register int j = 1; j <= len[i]; ++j)
        g[min + j] = s[i][j];
      max = min + len[i];
      for (register int j = max; j >= 0; --j)
        if (j + len[i] <= k && c[i + 1][k - j - len[i]] && f[i - 1][j]) {
          int L;
          int tmp = cmp(i, j, min, L);
          if (tmp == 0)
            f[i][j + len[i]] = 1;
        }
    }
    for (register int j = 0; j <= ml; ++j)
      f[i][j] |= f[i - 1][j];
    g[max + 1] = 0;
  }
  assert(strlen(g + 1) == k);
  puts(g + 1);
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#define cmax(a, b) (a < (b) ? a = (b), 1 : 0)
#define cmin(a, b) (a > (b) ? a = (b), 1 : 0)
#define dmin(a, b) ((a) < (b) ? (a) : (b))
#define dmax(a, b) ((a) > (b) ? (a) : (b))
#define regsiter register
#define CL fclose(stdin), fclose(stdout)
namespace io {
int F() {
  int n = 0, F = 1;
  char ch;
  while ((ch = getchar()) != '-' && (ch < '0' || ch > '9'))
    ;
  ch == '-' ? F = 0 : n = ch - '0';
  while ((ch = getchar()) >= '0' && ch <= '9')
    n = (n << 1) + (n << 3) + ch - '0';
  return F ? n : -n;
}
long long G() {
  long long n = 0, F = 1;
  char ch;
  while ((ch = getchar()) != '-' && (ch < '0' || ch > '9'))
    ;
  ch == '-' ? F = 0 : n = ch - '0';
  while ((ch = getchar()) >= '0' && ch <= '9')
    n = (n << 1) + (n << 3) + ch - '0';
  return F ? n : -n;
}
} // namespace io
#include <cassert>
const int S = 4000039;
const int M = 998244353;
bool c[2011][10011];
bool f[2011][10011];
char g[10011];
int h[10011];
char s[2011][10011];
int len[2011];
int ex[10011];
int max;
int slcp[10011];
int lcp[10011];
int cmp(int i, int j, int min, int &ans) {
  int l1 = lcp[j + 1];
  if (l1 < min - j) {
    ans = j + l1;
    if (l1 == len[i])
      return 0;
    if (s[i][l1 + 1] < g[j + l1 + 1])
      return -1;
    return 1;
  }
  if (j + len[i] == min)
    return 0;
  int l2 = slcp[min - j + 1];
  ans = min + l2;
  if (min + l2 == j + len[i])
    return 0;
  if (s[i][l2 + 1] > s[i][min - j + l2 + 1])
    return -1;
  return 1;
}
int main() {
  int n = io::F(), k = io::F();
  ex[0] = 1;
  for (register int i = 1; i <= k; ++i)
    ex[i] = (ex[i - 1] * (long long)S) % M;
  for (register int i = 1; i <= n; ++i)
    scanf("%s", s[i] + 1), len[i] = strlen(s[i] + 1);
  c[n + 1][0] = 1;
  for (register int i = n; i; --i)
    for (register int j = 0; j <= k; ++j) {
      c[i][j] = c[i + 1][j];
      if (j >= len[i])
        c[i][j] |= c[i + 1][j - len[i]];
    }
  f[0][0] = 1;
  for (register int i = 1; i <= n; ++i) {
    int min = -1;
    slcp[1] = len[i];
    int la = 0;
    for (register int j = 2; j <= len[i]; ++j) {
      if (j < la + slcp[la]) {
        int t = j - la + 1;
        if (t + slcp[t] - 1 < slcp[la])
          slcp[j] = slcp[t];
        else
          for (slcp[j] = la + slcp[la] - j, la = j;
               s[i][j + slcp[j]] == s[i][1 + slcp[j]]; ++slcp[j])
            ;
      } else {
        for (slcp[j] = 0; s[i][j + slcp[j]] == s[i][1 + slcp[j]]; ++slcp[j])
          ;
        la = j;
      }
    }
    la = 0;
    for (register int j = 1; j <= max; ++j) {
      if (j < la + lcp[la]) {
        int t = j - la + 1;
        if (t + slcp[t] - 1 < lcp[la])
          lcp[j] = slcp[t];
        else
          for (lcp[j] = la + lcp[la] - j, la = j;
               1 + lcp[j] <= len[i] && j + lcp[j] <= max &&
               s[i][1 + lcp[j]] == g[j + lcp[j]];
               ++lcp[j])
            ;
      } else {
        for (lcp[j] = 0; 1 + lcp[j] <= len[i] && j + lcp[j] <= max &&
                         s[i][1 + lcp[j]] == g[j + lcp[j]];
             ++lcp[j])
          ;
        la = j;
      }
    }
    int ml = max;
    for (register int j = max; j >= 0; --j)
      if (j + len[i] <= k && c[i + 1][k - j - len[i]] && f[i - 1][j])
        if (min == -1) {
          int l1 = lcp[j + 1];
          if (j == max || j + l1 == dmin(max, j + len[i]) ||
              s[i][l1 + 1] < g[j + l1 + 1])
            min = j, ml = j + l1;
        } else {
          int L;
          int tmp = cmp(i, j, min, L);
          if (tmp == -1) {
            min = j;
            ml = L;
          }
        }
    if (min != -1) {
      for (register int j = 1; j <= len[i]; ++j)
        g[min + j] = s[i][j];
      max = min + len[i];
      for (register int j = max; j >= 0; --j)
        if (j + len[i] <= k && c[i + 1][k - j - len[i]] && f[i - 1][j]) {
          int L;
          int tmp = cmp(i, j, min, L);
          if (tmp == 0)
            f[i][j + len[i]] = 1;
        }
    }
    for (register int j = 0; j <= ml; ++j)
      f[i][j] |= f[i - 1][j];
    g[max + 1] = 0;
  }
  assert(strlen(g + 1) == k);
  puts(g + 1);
  return 0;
}