zoukankan      html  css  js  c++  java
  • [Usaco2006 Dec]Milk Patterns

    Description

    农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天
    产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。
    John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的
    牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。
    比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。

    Input

    * Line 1: 两个整数 N,K。
    * Lines 2..N+1: 每行一个整数表示当天的质量值。

    Output

    * Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度

    Sample Input

    8 2
    1
    2
    3
    2
    3
    2
    3
    1
    
    
    
    

    Sample Output

    4
    
    
    
    思路:和上一题一样,求最长可重叠的重复子串,但多了一个限制,要至少出现k次。二分,按height分组后统计是否有一个组的后缀个数大于k,如果有,那么就表明这一组的公共前缀在原字符串里出现了k次以上,那么就符合要求,return true;
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxl=40010;
    int sa[maxl],tsa[maxl],rank[maxl],trank[maxl],sum[1000010],n,s[maxl],k,ans,h[maxl];
    
    void sorts(int j){
    	memset(sum,0,sizeof(sum));
    	for (int i=1;i<=n;i++) sum[rank[i+j]]++;
    	for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
    	for (int i=n;i;i--) tsa[sum[rank[i+j]]--]=i;
    	
    	memset(sum,0,sizeof(sum));
    	for (int i=1;i<=n;i++) sum[rank[tsa[i]]]++;
    	for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
    	for (int i=n;i;i--) sa[sum[rank[tsa[i]]]--]=tsa[i]; 
    }
    
    void getsa(){
    	for (int i=1;i<=n;i++) trank[i]=s[i];
    	for (int i=1;i<=n;i++) sum[trank[i]]++;//for (;;);
    	for (int i=1;i<=1000000;i++) sum[i]+=sum[i-1];
    	for (int i=n;i;i--) sa[sum[trank[i]]--]=i;
    	rank[sa[1]]=1;
    	for (int i=2,p=1;i<=n;i++){
    		if (trank[sa[i]]!=trank[sa[i-1]]) p++;
    		rank[sa[i]]=p;
    	}
    	for (int j=1;j<=n;j*=2){
    		sorts(j);
    		trank[sa[1]]=1;
    		for (int i=2,p=1;i<=n;i++){
    			if (rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+j]!=rank[sa[i-1]+j]) p++;
    			trank[sa[i]]=p;
    		}
    		memcpy(rank,trank,sizeof(rank));
    	}
    }
    
    void geth(){
    	for (int i=1,j=0;i<=n;i++){
    		if (rank[i]==1) continue;
    		while (s[i+j]==s[sa[rank[i]-1]+j]) j++;
    		h[rank[i]]=j;
    		if (j) j--; 
    	}
    }
    
    bool check(int lim){
    	int len=1,maxs=0,mins=100000000;
    	for (int i=2;i<=n;i++){
    		if (h[i]<lim){maxs=0,mins=100000000,len=0;} 
    		maxs=max(maxs,sa[i]);
    		mins=min(mins,sa[i]);
    		len++;
    		if (len>=k) return true;
    	}
    	return false;
    }
    
    int main(){
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&s[i]);
    	getsa();
    	geth();
    	int l=1,r=20000,mid=(l+r)>>1;
    	while (l<=r){
    		if (check(mid)){
    			l=mid+1;
    			ans=mid;
    		}
    		else r=mid-1;
    		mid=(l+r)>>1;
    	}
    	printf("%d
    ",ans);
    	//for (;;);
    	return 0;
    }
    


  • 相关阅读:
    frp穿透.md
    6_模板与渲染.md
    4_多数据格式返回请求结果.md
    3_请求参数绑定与多数据格式处理.md
    5_中间件.md
    1_go_gin介绍.md
    2_Gin网络请求与路由处理.md
    14_文件.md
    firefox油猴脚本编写.md
    js 四舍五入
  • 原文地址:https://www.cnblogs.com/thythy/p/5493606.html
Copyright © 2011-2022 走看看