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

传送门: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 long

inline 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.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 11:55:44

【SuffixArray】bzoj1717 [Usaco2006 Dec] Milk Patterns 产奶的模式的相关文章

[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1297  Solved: 705 [Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到100

[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案

Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec 题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度. 注释:$1\le n\le 2\cdot 10^4$,$2\le k\le n$. 想法:不难想到二分答案,现在我们考虑如何验证. 这里就是后缀数组的一个妙用了. 我们对原串建立后缀数组,观察$ht$数组. 考虑当前二分出来的$mid$.如果有至少连续$k$的$ht$值都不小于$mid$,那么$k$就是合法的. 故此我们直接扫$ht$数组看看

bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+二分)

1 /* 2 求可重叠的至少重复K次的最长字串 3 以1为下标起点,因为a[i]最大到1000000,所以要先离散一下 4 二分长度len 5 然后O(n)检验 6 后看h[i]是否有连续的一段h[i]大于len的,并且h[i]连续的长度大于K则满足 7 */ 8 #include<stdio.h> 9 #include<string.h> 10 #include<algorithm> 11 using namespace std; 12 const int maxn

[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)

以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列SA[1],SA[2],……,SA[n],并且保证Suffix(SA[i])<Suffix(SA[i+1]),1≤i<n. 也就是将S的n个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入SA中. height数组:定义height[i]=suffix(sa[i-1])和suffix(sa[

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1017  Solved: 561[Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一个0到1000000之间的

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; const int maxn = 20009; struct HASH { int id[maxn], N; HASH() { N = 0; } inline void work() { sort(id, id + N); N

【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 SA+二分

Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一个0到1000000之间的数.并且John记录了N(1<=N<=20000)天的牛奶质量值.他想知道最长的出现了至少K(2<=K<=N)次的模式的长度.比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次.当K=2时,这个长度为4. Input * Line

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式

Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到1000000之间的数.并且John记录了N(1<=N<=20000)天的牛奶质量值.他想知道最长的出现了至少K(2<=K<=N)次的模式的长度.比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次.当K=2时,这个长度为4. Inp

BZOJ_1717_[Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组

Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一个0到1000000之间的数.并且John记录了N(1<=N<=20000)天的牛奶质量值.他想知道最长的出现了至少K(2<=K<=N)次的模式的长度.比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次.当K=2时,这个长度为4. Input * Line