BZOJ1717: [Usaco2006 Dec] Milk Patterns Milk Production Model (Suffix Array + Monotone Queue)

Keywords: C++

1717: [Usaco 2006 Dec] Milk Patterns Milk Production Model

 

Description

Farmer John found that the quality of milk produced by his cows had been changing. After careful investigation, he found that although he could not foresee the quality of milk produced tomorrow, there were many overlaps in the quality of milk produced for several consecutive days. We call it a "model". John's milk can be given a number between 0 and 1000000 by quality. And John recorded the milk quality value of N (1 <=N <=20000) days. He wanted to know the length of the longest pattern with at least K (2 <= K <= N) times. For example, 23 23 23 appeared twice in 12 3 2 3 2 3 3 1. When K=2, the length is 4.

 

Input

* Line 1: Two integers N,K.

* Lines 2. N + 1: An integer per line represents the quality value of the day.

 

Output

* Line 1: An integer: the longest pattern length in N days with at least K occurrences

 

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

 

Explanation:

 

Seeing that the Internet is basically using two points, so I intend to have a monotonous queue of practices! uuuuuuuuuu
 
Title:
The title should be repeated k times and the length of the longest string.
 
Analysis:
First, we need to know that the LCP of two non-adjacent strings is the minimum value equal to the height s between them (LCP definition); secondly, we can find such a property, assuming that:
   A
   B
   C
   D
      E
price: The value of a queue starting with each string and length k;
  
(height s arranged from small to large SA arrays) and k=2 at this time. If the last string in the answer is E, then the answer is between D and E.
 
The minimum value of height; suppose the last string is B, then the answer is the minimum value of height between A and B; do you have any clues here? I am
 
The answer is that in a queue with each string as its head (or tail) and k as its length, each price is the smallest height s in its queue according to the above properties.
 
Value; we just need to find out the smallest price is our answer! Maybe you'll ask, isn't that at least? In fact, you can imagine that we have met the conditions of k.
 
Later, if we continue to increase the length of the team, if a height is larger than the current price, then it has no effect on our price (because of the sex above).
 
If a height is smaller than the current price, our price will become smaller, which does not meet our needs, so we only need O(n) progress.
 
Line monotonic queue maintenance minimum, a minimum price can be obtained!
 
Be careful:
Because the data may be large, it needs to be discretized!
 
Code:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int len,m,ki;
int str[20010];
int rank[20010],buc[20010],SA[20010],y[20010];
int belong[1000010],cnt;
void suffix()
{
    m=len;
    for(int i=0;i<m;i++) buc[i]=0;
    for(int i=0;i<len;i++) buc[rank[i]=belong[str[i]]]++;
    for(int i=1;i<m;i++) buc[i]+=buc[i-1];
    for(int i=len-1;i>=0;i--) SA[--buc[rank[i]]]=i;
    for(int k=1;k<len;k<<=1)
    {
        int p=0;
        for(int i=len-1;i>=len-k;i--) y[p++]=i;
        for(int i=0;i<len;i++) if(SA[i]>=k) y[p++]=SA[i]-k;
        for(int i=0;i<m;i++) buc[i]=0;
        for(int i=0;i<len;i++) buc[rank[y[i]]]++;
        for(int i=1;i<m;i++) buc[i]+=buc[i-1];
        for(int i=len-1;i>=0;i--) SA[--buc[rank[y[i]]]]=y[i];
        swap(rank,y);p=1;
        rank[SA[0]]=0;
        for(int i=1;i<len;i++)
        {
            if(y[SA[i-1]]==y[SA[i]]&&y[SA[i-1]+k]==y[SA[i]+k])
            rank[SA[i]]=p-1;
            else rank[SA[i]]=p++;
        }
        if(p>=len) break;
        m=p;
    }
}
int height[20010];
struct node
{
    int place,price;
}t[20010];

int main()
{
    freopen("a.in","r",stdin);
    scanf("%d%d",&len,&ki);
    int imax=0;
    for(int i=0;i<len;i++) 
    {
        scanf("%d",&str[i]);
        belong[str[i]]++;
        imax=max(str[i],imax);
    }
    for(int i=0;i<=imax;i++) if(belong[i]) belong[i]=cnt++;
    suffix();
    int x=0;
    for(int i=0;i<len;i++) rank[SA[i]]=i;
    for(int i=0;i<len;i++)
    {
        if(rank[i]==0) continue;
        if(x) x--;
        int j=SA[rank[i]-1];
        while(str[i+x]==str[j+x]&&x+i<len&&x+j<len) x++;
        height[rank[i]]=x;
    }
    int ans=0;
    int now=len-1;
    int l=0,r=-1;
    while(now>=0)
    {    
        while(t[l].place-now>=ki-1) l++;
        while(t[r].price>=height[now]&&r>=l) r--;
        t[++r].price=height[now];t[r].place=now; 
        if(len-now+1>=ki) 
        {    
            if(t[l].price>ans) ans=t[l].price;
        }
        now--;        
    }
    printf("%d\n",ans);
    return 0;
}

 

Do not reprint without the permission of the blogger!

Posted by jonker on Fri, 11 Jan 2019 14:03:11 -0800