[SDOI2008] Sandy card - suffix array

Description

\ (Sandy \) and \ (Sue \) is interested in collecting cards face altogether.

However, \ (Sue \) collect cards are beautiful because of characters on the card, and \ (Sandy \) is to accumulate cards exchange stunning character models.

Each card marked by some of the figures, the \ (I \) sequence length of cards \ (M_i \) , in order to convert the character model must first be set to \ (N \) cards, for which \ (N \) cards, if they have one and the same as the length of the substring \ (K \) , it is possible to convert a rating of \ (K \) character model. The same definition as: two sub-strings of the same length and a string of all the elements becomes plus a number of other string.

\ (Sandy \) is far less than the required number of cards \ (N \) , so \ (Sue \) decided to \ (Sandy \) birthday cards sent to his \ (Sandy \) , in \ (Sue \) with the help of, \ (Sandy \) finally set enough of N cards, however, \ (Sandy \) is not clear that he can exchange to which level of the character model, now, would you please help \ (Sandy \) and \ (Sue \) , look at their highest level of character models which can be obtained.

Solution

Determined directly after each string of differential longest common substring.

Code

#include <bits/stdc++.h>
using namespace std;

inline int ty() {
    char ch = getchar(); int x = 0, f = 1;
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

const int _  = 1000 + 10;
const int __ = _ * _;
int N, n, s[__], belong[__], rnk[__], sa[__], height[__];

void SA() {
    static int t[__], a[__], buc[__], fir[__], sec[__], tmp[__];
    copy(s + 1, s + N + 1, t + 1);
    sort(t + 1, t + N + 1);
    int *end = unique(t + 1, t + N + 1);
    for (int i = 1; i <= N; ++i) a[i] = lower_bound(t + 1, end, s[i]) - t;
    fill(buc + 1, buc + N + 1, 0);
    for (int i = 1; i <= N; ++i) ++buc[a[i]];
    for (int i = 1; i <= N; ++i) buc[i] += buc[i - 1];
    for (int i = 1; i <= N; ++i) rnk[i] = buc[a[i] - 1] + 1;
    for (int len = 1; len <= N; len <<= 1) {
        for (int i = 1; i <= N; ++i) {
            fir[i] = rnk[i];
            sec[i] = i + len > N ? 0 : rnk[i + len];
        }
        fill(buc + 1, buc + N + 1, 0);
        for (int i = 1; i <= N; ++i) ++buc[sec[i]];
        for (int i = 1; i <= N; ++i) buc[i] += buc[i - 1];
        for (int i = 1; i <= N; ++i) tmp[N - --buc[sec[i]]] = i;
        fill(buc + 1, buc + N + 1, 0);
        for (int i = 1; i <= N; ++i) ++buc[fir[i]];
        for (int i = 1; i <= N; ++i) buc[i] += buc[i - 1];
        for (int i = 1, j; i <= N; ++i) {
            j = tmp[i];
            sa[buc[fir[j]]--] = j;
        }
        bool uni = true;
        for (int i = 1, j, last = 0; i <= N; ++i) {
            j = sa[i];
            if (!last) rnk[j] = 1;
            else if (fir[j] == fir[last] && sec[j] == sec[last])
                rnk[j] = rnk[last], uni = false;
            else rnk[j] = rnk[last] + 1;
            last = j;
        }
        if (uni) break;
    }
    for (int i = 1, k = 0; i <= N; ++i) {
        if (rnk[i] == 1) k = 0;
        else {
            if (k > 0) --k;
            int j = sa[rnk[i] - 1];
            while (i + k <= N && j + k <= N && a[i + k] == a[j + k]) ++k;
        }
        height[rnk[i]] = k;
    }
}

bool check(int k) {
    static int tot, vis[_];
    int cnt = 0;
    ++tot;
    for (int i = 1; i <= N; ++i) {
        if (height[i] < k) ++tot, cnt = 0;
        else {
            if (vis[belong[sa[i]]] != tot)
                ++cnt, vis[belong[sa[i]]] = tot;
            if (vis[belong[sa[i - 1]]] != tot)
                ++cnt, vis[belong[sa[i - 1]]] = tot;
            if (cnt == n) return true;
        }
    }
    return false;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("sandy.in", "r", stdin);
    freopen("sandy.out", "w", stdout);
#endif
    static int t[_];
    n = ty();
    int now = 0;
    for (int i = 1; i <= n; ++i) {
        ++now;
        int m = ty();
        for (int j = 1; j <= m; ++j) t[j] = ty();
        for (int j = 1; j <= m; ++j) t[j] = t[j + 1] - t[j];
        for (int j = now; j <= now + m - 1; ++j)
            s[j] = t[j - now + 1], belong[j] = i;
        now += m - 1;
        s[++now] = 128 + i;
    }
    N = now;
    SA();
    int l = 0, r = N;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    printf("%d\n", l + 1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/newbielyx/p/12161485.html