8
18
2015
0

POJ3261 -- Milk Patterns

Milk Patterns

Description

Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

Input

Line 1: Two space-separated integers: N and K 
Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.

Output

Line 1: One integer, the length of the longest pattern which occurs at least K times

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

 

题意大致为求可重叠的k次最长重复子串长度

我们先来个后缀数组,然后二分答案 and 验证答案正确性。。。

关于 验证 答案len の 正确性:

        将排序后的后缀分成若干组,其中每组后缀之间的height值不小于等于len...

        判断有没有一组后缀的个数不小于k,

            如果有,那么存在k个子串满足条件。。。

            否则不存在。。。

 

详情请看 罗穗骞犇的《后缀数组——处理字符串的有力工具》

 

#include<cstdio>
#include<cstring>
#include<iostream>
#define MaxN 1000010
using namespace std;
int n,k,ans;
int s[MaxN];
int rank[MaxN];
int height[MaxN];
int sa[MaxN];
int w[MaxN];
void SA(){
	int *x=rank;
	int *y=height;
	int m=1e6+1;
	for (int i=1;i<=n;++i) ++w[x[i]=s[i]];
	for (int i=2;i<=m;++i) w[i]+=w[i-1];
	for (int i=1;i<=n;++i) sa[w[x[i]]--]=i;
	for (int k=1;k<n;k<<=1,swap(x,y)){
		int t=0;
		for (int i=n-k+1;i<=n;++i) y[++t]=i;
		for (int i=1;i<=n;++i)
		    if (sa[i]-k>0) y[++t]=sa[i]-k;
		memset(w+1,0,sizeof(int)*m);

		for (int i=1;i<=n;++i) ++w[x[i]];
		for (int i=2;i<=m;++i) w[i]+=w[i-1];
		for (int i=n;i;--i) sa[w[x[y[i]]]--]=y[i];
	    m=0;
		for (int i=1;i<=n;++i){
			int u=sa[i],v=sa[i-1];
			y[u]=i==1||x[u]!=x[v]||x[u+k]!=x[v+k]?++m:m;
		} 
		if (n==m) break;
	}
	if (rank!=y) memcpy(rank+1,y+1,sizeof(int)*n); 
	int h=0;
	for (int u=1;u<=n;++u){
	    if (h) --h;
	    int v=sa[rank[u]-1];
		while (s[u+h]==s[v+h]) ++h;
		height[rank[u]]=h;
	}
}
bool check(int len){
	int cnt=0;
	for (int i=1;i<=n;++i)
	    if (height[i]<len) cnt=0;
	    else if (++cnt==k-1) return true;
	return false;
}
int main(){
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;++i)
	    scanf("%d",&s[i]),++s[i];
	SA();
	int l=0,r=n;
	for (;l<=r;){
		int mid=(l+r)/2;
		if (check(mid)){
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	printf("%d\n",ans);
}
Category: POJ | Tags: POJ Sa 字符串 | Read Count: 365

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com