bzoj 2251 [2010Beijing Wc]外星联络 后缀数组

题面

题目传送门

解法

用后缀数组求出height数组,然后暴力即可

时间复杂度:\(O(n^2)\)

代码

#include <bits/stdc++.h>
#define N 3010
using namespace std;
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int n, st[N];
struct SuffixArray {
    int x[N], y[N], sa[N], rnk[N], cnt[N], height[N];
    void build() {
        int m = 2;
        for (int i = 1; i <= n; i++) cnt[x[i] = st[i]]++;
        for (int i = 2; i <= m; i++) cnt[i] += cnt[i - 1];
        for (int i = n; i; i--) sa[cnt[x[i]]--] = i;
        for (int k = 1; k <= n; k <<= 1) {
            int num = 0;
            for (int i = n - k + 1; i <= n; i++) y[++num] = i;
            for (int i = 1; i <= n; i++)
                if (sa[i] > k) y[++num] = sa[i] - k;
            for (int i = 1; i <= m; i++) cnt[i] = 0;
            for (int i = 1; i <= n; i++) cnt[x[i]]++;
            for (int i = 2; i <= m; i++) cnt[i] += cnt[i - 1];
            for (int i = n; i; i--) sa[cnt[x[y[i]]]--] = y[i], y[i] = 0;
            swap(x, y); x[sa[1]] = 1, num = 1;
            for (int i = 2; i <= n; i++)
                x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k]) ? num : ++num;
            if (num == n) break; m = num;
        }
        for (int i = 1; i <= n; i++) rnk[sa[i]] = i;
        int k = 0;
        for (int i = 1; i <= n; i++) {
            if (rnk[i] == 1) continue;
            if (k) k--; int j = sa[rnk[i] - 1];
            while (i + k <= n && j + k <= n && st[i + k] == st[j + k]) k++;
            height[rnk[i]] = k;
        }
    }
    void query() {
        int mx = 0;
        for (int i = 2; i <= n; i++) {
            if (height[i] > height[i - 1]) {
                for (int j = mx + 1; j <= height[i]; j++) {
                    int k = i, tot = 1;
                    while (height[k] >= j) k++, tot++;
                    cout << tot << "\n";
                }
            }
            mx = height[i];
        }
    }
} SA;
int main() {
    read(n);
    for (int i = 1; i <= n; i++) {
        char c = getchar();
        while (!isdigit(c)) c = getchar();
        st[i] = c - '0' + 1;
    }
    SA.build(); SA.query();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/copperoxide/p/9478362.html