zoukankan      html  css  js  c++  java
  • [Usaco2006 Dec]Milk Patterns

    [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次的模式的长度 

    Sample Input

    8 2
    1
    2
    3
    2
    3
    2
    3
    1
    
    
    
    

    Sample Output

    4
    

    Source

    后缀数组

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

    这题还是要先离散化一下,不然可能会MLE

    code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define maxn 30010
     5 using namespace std;
     6 char ch;
     7 int n,k,max_val,tot,head,tail,s[maxn],num[maxn],SA[maxn],rank[maxn],tmp[maxn],sum[maxn],height[maxn];
     8 struct DATA{
     9     int val,tim;
    10 }list[maxn];
    11 inline bool isdigit(char ch){return '0'<=ch&&ch<='9';}
    12 inline void read(int &x){
    13     for (ch=getchar();!isdigit(ch);ch=getchar());
    14     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    15 }
    16 inline bool cmp(int a,int b){return s[a]<s[b];}
    17 void prepare(){
    18     sort(num+1,num+1+n,cmp);
    19     for (int i=1,pre=-1;i<=n;i++){
    20         if (s[num[i]]!=pre) pre=s[num[i]],++max_val;
    21         s[num[i]]=max_val;
    22     }
    23 }
    24 void get_SA(){
    25     for (int i=1;i<=n;i++) sum[tmp[i]=s[i]]++;
    26     for (int i=1;i<=max_val;i++) sum[i]+=sum[i-1];
    27     for (int i=n;i>=1;i--) SA[sum[tmp[i]]--]=i;
    28     rank[SA[1]]=tot=1;
    29     for (int i=2;i<=n;i++){
    30         if (tmp[SA[i]]!=tmp[SA[i-1]]) tot++;
    31         rank[SA[i]]=tot;    
    32     }
    33     for (int len=1;len<=n;len<<=1){
    34         memset(sum,0,sizeof(sum));
    35         for (int i=1;i<=n;i++) sum[rank[i+len]]++;
    36         for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
    37         for (int i=n;i>=1;i--) tmp[sum[rank[i+len]]--]=i;
    38         memset(sum,0,sizeof(sum));
    39         for (int i=1;i<=n;i++) sum[rank[tmp[i]]]++;
    40         for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
    41         for (int i=n;i>=1;i--) SA[sum[rank[tmp[i]]]--]=tmp[i];
    42         tmp[SA[1]]=tot=1;
    43         for (int i=2;i<=n;i++){
    44             if (rank[SA[i]]!=rank[SA[i-1]]||rank[SA[i]+len]!=rank[SA[i-1]+len]) tot++;
    45             tmp[SA[i]]=tot;    
    46         }
    47         for (int i=1;i<=n;i++) rank[i]=tmp[i];        
    48     }
    49 }
    50 void get_height(){
    51     for (int i=1,j=0;i<=n;i++){
    52         if (rank[i]==1) continue;
    53         while (s[i+j]==s[SA[rank[i]-1]+j]) j++;    
    54         height[rank[i]]=j;
    55         if (j>0) j--;
    56     }
    57 }
    58 int main(){
    59     read(n),read(k);
    60     for (int i=1;i<=n;i++) read(s[i]),num[i]=i;
    61     prepare(),get_SA(),get_height();
    62     k--,head=1,tail=0,max_val=0;
    63     for (int i=2;i<=n;i++){
    64         while (head<=tail&&i-list[head].tim>=k) head++;
    65         while (head<=tail&&height[i]<list[tail].val) tail--;
    66         list[++tail]=(DATA){height[i],i};
    67         if (i>k&&max_val<list[head].val) max_val=list[head].val;
    68     }
    69     printf("%d
    ",max_val);
    70     return 0;    
    71 }
  • 相关阅读:
    Vasya and Endless Credits CodeForces
    Dreamoon and Strings CodeForces
    Online Meeting CodeForces
    数塔取数 基础dp
    1001 数组中和等于K的数对 1090 3个数和为0
    1091 线段的重叠
    51nod 最小周长
    走格子 51nod
    1289 大鱼吃小鱼
    POJ 1979 Red and Black
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/4124834.html
Copyright © 2011-2022 走看看