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

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

Output

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

题解:

至少K次可以理解为出现K次,更好满足。

离散化后求这个串的后缀数组,rank数组及height数组。

答案应该是height数组中连续K-1个值的最小值的最大值。

可以用一个单调队列维护。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
//by zrt
//problem:
using namespace std;
int n,K;
const int MAXN=20005;
int s[MAXN];
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],rank[MAXN],height[MAXN];
void build_sa(int m){
    memset(t,-1,sizeof t);
    memset(t2,-1,sizeof t2);
    int *x=t,*y=t2;
    for(int i=0;i<m;i++) c[i]=0;
    for(int i=0;i<n;i++) c[x[i]=s[i]]++;
    for(int i=1;i<m;i++) c[i]+=c[i-1];
    for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        for(int i=n-k;i<n;i++) y[p++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[y[i]]]++;
        for(int i=0;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];

        swap(x,y);
        p=1;x[sa[0]]=0;
        for(int i=1;i<n;i++){
            x[sa[i]]= y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        }
        if(p>=n) break;
        m=p;
    }
}

int tot;
struct N{
    int x,w;
    N(int a=0,int b=0){
        x=a,w=b;
    }
};
struct dddl{
    N q[MAXN];
    int h,t;
    void insert(N a){
        while(h!=t&&q[t-1].w>=a.w) t--;
        q[t++]=a;
    }
    void pop(int pos){
        if(q[h].x==pos) h++;
    }
    int ask(){
        return q[h].w;
    }
}dddl;
int main(){
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    scanf("%d%d",&n,&K);
    for(int i=0;i<n;i++){
        scanf("%d",&s[i]);
        c[i+1]=s[i];
    }
    sort(c+1,c+n+1);
    tot=unique(c+1,c+n+1)-(c+1);
    for(int i=0;i<n;i++){
        s[i]=lower_bound(c+1,c+tot+1,s[i])-c;
    }
    s[n]=-1;
    build_sa(tot+1);
    for(int i=0;i<n;i++) rank[sa[i]]=i;
    int k=0;
    for(int i=0;i<n;i++){
        if(k) k--;
        if(!rank[i]) continue;
        int j=sa[rank[i]-1];
        while(s[i+k]==s[j+k]) k++;
        height[rank[i]]=k;
    }
    int ans=0;
    for(int i=0;i<n;i++){
        dddl.insert(N(i,height[i]));
        dddl.pop(i-K+1);
        ans=max(ans,dddl.ask());
    }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-08-10 21:28:08

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式的相关文章

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

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

[题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=1717 [题目大意] 求一个最长的串,使得其在母串中出现的次数达到要求 [题解] 二分答案,利用后缀数组求出的height数组进行检验 [代码] #include <cstdio> #include <cstring> using namespace std; const int N=2000010; int n,k,rank[N],sa[N],h[N],tmp[N],cn

bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式【后缀自动机】

就是后缀自动机的板子嘛..构造完自动机之后拓扑一下,记录size,对于size大于k的点和ans取max #include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; const int N=100005; int n,m,a[N],cur=1,cnt=1; int read() { int r=0,f=1; char p=getchar();

【bzoj】1717 [Usaco2006 Dec]Milk Patterns 产奶的模式

[算法]后缀数组 [题解]后缀数组 由于m太大,先离散化. 然后处理SA和LCP. 最后用单调队列处理即可. 注意实际上队列头尾长度限制是K-1. 删队尾不要删过头 i≥K才能开始统计答案. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=20010; int n,m,s[maxn],x[maxn],y[maxn],base[maxn],

[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 产奶的模式 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. Input * Line