Balkan OI 2015 - Clarkson

Author: Andi Qu

There are two parts to the solution:

  1. Finding the array FF such that the substring S[i:i+Fi]S[i:i + F_i] is a substring of TT and FiF_i is maximal.
  2. Binary searching for the answer.

Part 1 - Finding FF

This is the hardest part of the problem. We will solve it using a suffix array and LCP.

First, join SS and TT together with a ~ character and build the suffix array of the resulting string. Using this suffix array, we can then build the LCP array. (If you are unfamiliar with this, check out this Codeforces course.)

Recall that the LCP of two suffixes is the range minimum of the elements of the LCP array between those two suffixes.

Since we want FiF_i to be maximal, we thus only need to check two suffixes for each ii - the two closest suffixes to the suffix starting on S[i]S[i]! We can find the indices of these two suffixes using a std::set.

This part of the algorithm runs in O((N+M)log(N+M))\mathcal{O}((N + M) \log (N + M)) time (but slower suffix array constructions are fast enough to pass as well).

Part 2 - Binary Searching

Binary search works because if we can achieve a minimum length ll, then we can also achieve a minimum length k<lk < l (since we don't necessarily need a substring of length kk; we only need the lengths of all substrings to be of length at least kk.)

Here's how we check whether we can achieve a certain minimum length ll:

Let dp[i]dp[i] be whether we can make S[i:N]S[i : N] using substrings from TT of size at least ll. Clearly, if dp[j]dp[j] is true for any j[i+l,i+Fi]j \in [i + l, i + F_i], then dp[i]dp[i] is also true.

To check whether such a jj exists, we can store all indices where dp[j]dp[j] is true in a set and check whether any of them lie in the range [i+l,i+Fi][i + l, i + F_i].

This part of the algorithm runs in O(Nlog2N)\mathcal{O}(N \log^2 N) time (or O(NlogN)\mathcal{O}(N \log N) time if you do the check in O(N)\mathcal{O}(N)).

Implementation

#include <bits/stdc++.h>
using namespace std;
string s, t, u;
int n, m, l;
int ord[200005], nord[200005], suff[200005], rev[200005], p = 1;
int lcp[200005][20], match[100000], h = 0;
set<int> topgear;
void build_suffix_arr() {

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!