POJ 3561

来源:互联网 发布:知乎安卓屏幕录像软件 编辑:程序博客网 时间:2024/06/05 08:23

题目链接:http://poj.org/problem?id=3261

题意:求一个序列中,出现超过k次的子序列的最长长度

思路:我做的第一道hash题目,方法就是用二分来逼近最长长度,用hash来计算子序列出现的次数。hash水题,要注意的就是取模,还有二分的边界条件。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=20000+10;int arr[N];typedef unsigned long long ll;const int Mod=1e6+7;ll xp[N],hash[N],hash2[N];//unsigned long long可以自动取模int n,k;bool check(int len){    int i,j;    for(i=0;i<n-(len-1);i++)//去长度为len的hash值    {        hash2[i]=hash[i]-hash[i+len]*xp[len];    }    sort(hash2,hash2+n-(len-1));    int maxx=0,cnt=1;    for(i=1;i<n-(len-1);i++)    {        if(hash2[i]==hash2[i-1]) cnt++;        else cnt=1;        if(cnt>maxx)//找最长的长度            maxx=cnt;    }    return maxx>=k;}int main (){    //freopen("in.txt","r",stdin);    int i,j;    xp[0]=1;    for(i=1;i<N;i++)        xp[i]=xp[i-1]*Mod;    while(~scanf("%d %d",&n,&k))    {        for(i=0;i<n;i++)            scanf("%d",&arr[i]);        hash[n]=0;        for(i=n-1;i>=0;i--)//取hash值            hash[i]=hash[i+1]*Mod+arr[i];        int l=1,r=n;        while(l<r)//二分,边界条件比较坑,好像一定要一个加,一个减否则停不下来或者错        {            int mid=(l+r)/2+1;            if(check(mid)) l=mid;            else r=mid-1;        }        printf("%d\n",l);    }    return 0;}

0 0
原创粉丝点击