POJ 3261 Milk Patterns

来源:互联网 发布:黎东方知乎 编辑:程序博客网 时间:2024/06/11 13:01

大概又是一道论文题。问可重叠的至少重复k次的子序列的最大长度。

毅然决然二分长度,然后搜一遍就好了。


#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int maxn=20005;const int maxm=100005;int n,k;int s[maxn];int c[maxm];int height[maxn],sa[maxn],rank[maxn];int temp[maxm],tmp[maxm];int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();return x;}void getsa(){int *x=tmp,*y=temp,cnt,m=maxm-2;for(int i=1;i<=m;i++)c[i]=0;for(int i=1;i<=n;i++)c[x[i]=s[i]]++;for(int i=2;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;for(int k=1;k<=n;k<<=1){cnt=0;for(int i=n-k+1;i<=n;i++)y[++cnt]=i;for(int i=1;i<=n;i++)if(sa[i]>k)y[++cnt]=sa[i]-k;for(int i=1;i<=m;i++)c[i]=0;for(int i=1;i<=n;i++)c[x[y[i]]]++;for(int i=2;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i];swap(x,y);x[sa[1]]=cnt=1;for(int i=2;i<=n;i++)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?cnt:++cnt;if(cnt>=n)break;m=cnt;}for(int i=1;i<=n;i++)rank[sa[i]]=i;cnt=0;for(int i=1;i<=n;i++){if(cnt)cnt--;int j=sa[rank[i]-1];while(s[i+cnt]==s[j+cnt])cnt++;height[rank[i]]=cnt;}}bool judge(int mid){int num=0;for(int i=1;i<=n;i++){if(height[i]>=mid){num++;if(num>=k-1)return true;}else num=0;}return false;}int main(){scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)s[i]=read()+1;getsa();int l=0,r=n+1,mid;while(l<r){mid=l+r+1>>1;if(!judge(mid))r=mid-1;else l=mid;}printf("%d",l);}