[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到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 1: 两个整数 N,K。

* Lines 2..N+1: 每行一个整数表示当天的质量值。

Output

* Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

求出后缀数组以及height数组,二分答案,如果有连续$k-1$个的height>=mid则可行

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 20000 + 10;
int n, m, k, s[maxn];
int *p[maxn], cnt, last;
class cmp1{
    public:
        bool operator () (int *a, int *b){
            return *a < *b;
        }
};
int tax[maxn], tp[maxn], sa[maxn], rank[maxn], height[maxn];
inline bool cmp(int *r, int x, int y, int l){
    return r[x] == r[y] && r[x + l] == r[y + l];
}
inline void rsort(){
    for(int i = 0; i <= m; i++) tax[i] = 0;
    for(int i = 1; i <= n; i++) tax[rank[tp[i]]]++;
    for(int i = 1; i <= m; i++) tax[i] += tax[i - 1];
    for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i];
}
void suffix(){
    for(int i = 1; i <= n; i++){
        rank[i] = s[i];
        tp[i] = i;
    }
    m = n;
    rsort();
    for(int p, w = 1; w < n; w <<= 1, m = p){
        p = 0;
        for(int i = n - w + 1; i <= n; i++) tp[++p] = i;
        for(int i = 1; i <= n; i++) if(sa[i] > w) tp[++p] = sa[i] - w;
        rsort();
        swap(rank, tp);
        p = rank[sa[1]] = 1;
        for(int i = 2; i <= n; i++)
            rank[sa[i]] = cmp(tp, sa[i - 1], sa[i], w) ? p : ++p;
    }
    for(int i = 1, j, k = 0; i <= n; height[rank[i++]] = k)
        for(k ? k-- : 0, j = sa[rank[i] - 1]; s[i + k] == s[j + k]; k++);
}
inline bool Judge(int mid){
    int tot = 0;
    for(int i = 1; i <= n; i++)
        if(height[i] >= mid){
            tot++;
            if(tot == k - 1) return true;
        }
        else tot = 0;
    return false;
}
int main(){
    scanf("%d %d", &n, &k);
    for(int i = 1; i <= n; i++)    scanf("%d", p[i] = s + i);
    sort(p + 1, p + n + 1, cmp1());
    last = *p[1];
    *p[1] = cnt = 1;
    for(int i = 2; i <= n; i++){
        if(*p[i] != last) cnt++;
        last = *p[i];
        *p[i] = cnt;
    }
    suffix();
    int l = 1, r = n, mid, ans;
    while(l <= r){
        mid = l + r >> 1;
        if(Judge(mid)){
            ans = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}
时间: 2024-12-28 02:34:50

[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式的相关文章

[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$数组看看

【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--) #d

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