POJ-3261-Milk Patterns-二分+哈希

Milk Patterns

题意:

在一串数字中,求至少连续k次的最大子序列长度;

思路:

二分加哈希;

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn = 20005;
const int p = 233;

int n,k,a[maxn+5]; 
unsigned long long hash1[maxn+5],F[maxn+5]={1};        //F数组用来保存p的次方,可能是pow()不稳定,慎用
unsigned long long re[maxn+5];

bool judge(int x)
{
    memset(re,0,sizeof(re));
    int tot = 0;
    for(int i=1;i<=n-x+1;i++)
    {
        int r = i+x-1;
        re[++tot] = (hash1[r]-hash1[i-1]*F[r-i+1]);
    }
    sort(re+1,re+1+tot);
    int cnt=1,mmax=1;
    unsigned long long last = re[1];
    for(int i=2;i<=tot;i++)
    {
        if(re[i]==last)
        {
            cnt++;
            if(cnt>mmax)mmax = cnt;
        }
        else 
        {
            cnt=1;
        }
        last = re[i]; 
    }
    return mmax >= k;
}

int main(){
    scanf("%d%d",&n,&k);
    hash1[0]=0;
    F[0] = 1;
    for(int i=1;i<=n;i++)
    {
        F[i] = F[i-1]*p;                
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(i==1)hash1[i]=a[i];
        else 
            hash1[i] = hash1[i-1]*p +a[i];
    }
    int le = 1,ri = n;                    
    while(le+1<ri)
    {
        int mid = le + (ri-le)/2;
        if(judge(mid)) le = mid;
        else ri = mid;
    }
    printf("%d\n",le);
    return 0;
}

 

posted @ 2018-02-21 16:43  ckxkexing  阅读(138)  评论(0编辑  收藏  举报