Problem p00451 (C++)

Buggy submission (status: Runtime Error):
// AOJ 0528
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

const int NMAX = 20000;

int n, k;
int Rank[NMAX + 1];
int tmp[NMAX + 1];

bool compare_sa(int i, int j) {
  if (Rank[i] != Rank[j])
    return Rank[i] < Rank[j];
  else {
    int ri = i + k <= n ? Rank[i + k] : -1;
    int rj = j + k <= n ? Rank[j + k] : -1;
    return ri < rj;
  }
}

void construct_sa(string S, int *sa) {
  n = S.length();

  for (int i = 0; i <= n; i++) {
    sa[i] = i;
    Rank[i] = i < n ? S[i] : -1;
  }

  for (k = 1; k <= n; k *= 2) {
    sort(sa, sa + n + 1, compare_sa);

    tmp[sa[0]] = 0;
    for (int i = 1; i <= n; i++) {
      tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
    }

    for (int i = 0; i <= n; i++) {
      Rank[i] = tmp[i];
    }
  }
}

void construct_lcp(string S, int *sa, int *lcp) {
  int n = S.length();
  for (int i = 0; i <= n; i++)
    Rank[sa[i]] = i;

  int h = 0;
  lcp[0] = 0;
  for (int i = 0; i < n; i++) {
    int j = sa[Rank[i] - 1];

    if (h > 0)
      h--;
    for (; j + h < n and i + h < n; h++) {
      if (S[j + h] != S[i + h])
        break;
    }

    lcp[Rank[i] - 1] = h;
  }
}

string S, T;

const int LMAX = 4008;
int sa[LMAX], lcp[LMAX];

int solve() {
  int sl = S.length();
  S += '_' + T;

  construct_sa(S, sa);
  construct_lcp(S, sa, lcp);

  int ans = 0;
  for (int i = 0; i < S.length(); i++) {
    if ((sa[i] < sl) != (sa[i + 1] < sl)) {
      ans = max(ans, lcp[i]);
    }
  }
  return ans;
}

int main() {
  while (cin >> S >> T) {
    cout << solve() << endl;
  }
}

Fixed submission:
// AOJ 0528
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

const int NMAX = 20000;

int n, k;
int Rank[NMAX + 1];
int tmp[NMAX + 1];

bool compare_sa(int i, int j) {
  if (Rank[i] != Rank[j])
    return Rank[i] < Rank[j];
  else {
    int ri = i + k <= n ? Rank[i + k] : -1;
    int rj = j + k <= n ? Rank[j + k] : -1;
    return ri < rj;
  }
}

void construct_sa(string S, int *sa) {
  n = S.length();

  for (int i = 0; i <= n; i++) {
    sa[i] = i;
    Rank[i] = i < n ? S[i] : -1;
  }

  for (k = 1; k <= n; k *= 2) {
    sort(sa, sa + n + 1, compare_sa);

    tmp[sa[0]] = 0;
    for (int i = 1; i <= n; i++) {
      tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
    }

    for (int i = 0; i <= n; i++) {
      Rank[i] = tmp[i];
    }
  }
}

void construct_lcp(string S, int *sa, int *lcp) {
  int n = S.length();
  for (int i = 0; i <= n; i++)
    Rank[sa[i]] = i;

  int h = 0;
  lcp[0] = 0;
  for (int i = 0; i < n; i++) {
    int j = sa[Rank[i] - 1];

    if (h > 0)
      h--;
    for (; j + h < n and i + h < n; h++) {
      if (S[j + h] != S[i + h])
        break;
    }

    lcp[Rank[i] - 1] = h;
  }
}

string S, T;

const int LMAX = 20000;
int sa[LMAX], lcp[LMAX];

int solve() {
  int sl = S.length();
  S += '_' + T;

  construct_sa(S, sa);
  construct_lcp(S, sa, lcp);

  int ans = 0;
  for (int i = 0; i < S.length(); i++) {
    if ((sa[i] < sl) != (sa[i + 1] < sl)) {
      ans = max(ans, lcp[i]);
    }
  }
  return ans;
}

int main() {
  while (cin >> S >> T) {
    cout << solve() << endl;
  }
}