【SuffixArray】bzoj1717 [Usaco2006 Dec] Milk Patterns 产奶的模式

来源:互联网 发布:mac excel 下拉菜单 编辑:程序博客网 时间:2024/05/12 10:13

传送门:BZOJ1717

解题思路

先把正解说一说:单调队列或者二分
然后么。。为什么我写的这么长?!
是罗穗骞的论文题嘛……就当给后缀数组练手吧
可重叠k次重复字串

YM代码

#include <bits/stdc++.h>using namespace std;#define rep(i, a, b) for(int i = (a); i <= (b); i++)#define red(i, a, b) for(int i = (a); i >= (b); i--)#define ll long longinline int read() {    int x = 0;    char ch = getchar();    while(ch < '0' || ch > '9') ch = getchar();    while(ch >= '0' || ch <= '9') {        x *= 10; x += ch - '0';        ch = getchar();    }    return x;}const int N = 20005;int n, m, k, p, q, tot = 0;int a[N], num[N], hash[N], v[N], h[N], height[N], sa[2][N], rank[2][N];int find(int x) {    int l = 1, r = tot, ans = 0;    while(l <= r) {        int mid = (l + r) >> 1;        if (hash[mid] <= x) ans = mid, l = mid + 1;        else r = mid - 1;    }    return ans;}bool jud(int x) {    int tmp = 0;    rep(i, 1, n) {        if (height[i] >= x) {            tmp++;            if (tmp == m-1) return 1;        }else tmp = 0;    }    return 0;}void getans() {    k = 0;    rep(i, 1, n) {        if (rank[p][i] == 1) h[i] = 0;        else {            int j = sa[p][rank[p][i]-1];            while(a[i+k] == a[j+k]) k++;            h[i] = k;            if (k > 0) k--;        }    }    rep(i, 1, n) height[rank[p][i]] = h[i];    int l = 1, r = n, ans = 0;    while(l <= r) {        int mid = (l + r) >> 1;        if (jud(mid)) ans = mid, l = mid + 1;        else r = mid - 1;    }    printf("%d\n", ans);}void calsa(int sa[N], int rk[N], int SA[N], int RK[N]) {    rep(i, 1, n) v[rk[sa[i]]] = i;    red(i, n, 1) if (sa[i] > k) SA[v[rk[sa[i]-k]]--] = sa[i] - k;    rep(i, n-k+1, n) SA[v[rk[i]]--] = i;    rep(i, 1, n) RK[SA[i]] = RK[SA[i-1]] + (rk[SA[i]] != rk[SA[i-1]] || rk[SA[i]+k] != rk[SA[i-1]+k]);}void work() {    p = 0, q = 1; a[0] = -1;    rep(i, 1, n) v[a[i]]++;    rep(i, 1, n) v[i] += v[i-1];    rep(i, 1, n) sa[p][v[a[i]]--] = i;    rep(i, 1, n)        if(a[sa[p][i]] != a[sa[p][i-1]])             rank[p][sa[p][i]] = rank[p][sa[p][i-1]] + 1;        else rank[p][sa[p][i]] = rank[p][sa[p][i-1]];    k = 1;    while(k < n) {        calsa(sa[p], rank[p], sa[q], rank[q]);        p^=1; q^=1; k<<=1;    }    getans();}int main() {    scanf("%d%d", &n, &m);    rep(i, 1, n) {        scanf("%d", &a[i]);        num[i] = a[i];    }    sort(num + 1, num + n + 1);    hash[++tot] = num[1];    rep(i, 2, n) {        if (num[i] != num[i-1])             hash[++tot] = num[i];    }    rep(i, 1, n) a[i] = find(a[i]);    work();    return 0;}

尾声

好长好长…好长好长…
真的不想…一直做码题~~

End.

1 0
原创粉丝点击