zoukankan      html  css  js  c++  java
  • luoguP2852 [USACO06DEC]Milk Patterns

    题意

    显然如果有一个子串出现过(k)次,那么它必定是一个至少长为k的后缀序的(LCP),求出所有相邻的长为(k-1)(height)数组的最小值,在其中取最大值即可

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=20010;
    const int maxm=1000010;
    int n,m,num,ans;
    int a[maxn],sa[maxn],rk[maxn],oldrk[maxn],id[maxn],tmpid[maxn],cnt[maxm],height[maxn];
    multiset<int>s;
    inline bool check(int x,int y,int k){return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];}
    inline void sa_build()
    {
    	num=1000000;
    	for(int i=1;i<=n;i++)cnt[rk[i]=a[i]]++;
    	for(int i=1;i<=num;i++)cnt[i]+=cnt[i-1];
    	for(int i=n;i;i--)sa[cnt[rk[i]]--]=i;
    	for(int t=1;t<n;t<<=1)
    	{
    		int tot=0;
    		for(int i=n-t+1;i<=n;i++)id[++tot]=i;
    		for(int i=1;i<=n;i++)if(sa[i]>t)id[++tot]=sa[i]-t;
    		memset(cnt,0,sizeof(cnt));
    		for(int i=1;i<=n;i++)cnt[tmpid[i]=rk[id[i]]]++;
    		for(int i=1;i<=num;i++)cnt[i]+=cnt[i-1];
    		for(int i=n;i;i--)sa[cnt[tmpid[i]]--]=id[i];
    		memcpy(oldrk,rk,sizeof(rk));
    		tot=0;
    		for(int i=1;i<=n;i++)rk[sa[i]]=check(sa[i-1],sa[i],t)?tot:++tot;
    		num=tot;
    	}
    	for(int i=1,j=0;i<=n;i++)
    	{
    		if(j)j--;
    		while(a[i+j]==a[sa[rk[i]-1]+j])j++;
    		height[rk[i]]=j;
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);m--;
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	sa_build();
    	for(int i=1;i<=n;i++)
    	{
    		s.insert(height[i]);
    		if(i>m)s.erase(s.find(height[i-m]));
    		if(i>=m)ans=max(ans,*s.begin());
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    JQuery实现数组移除指定元素
    美团酒旅面经
    搜狗一面
    360面经
    头条面经
    搜狐笔试题
    kolakoski序列
    函数的节流
    隐藏元素的几种方法
    移动端适配与响应式布局
  • 原文地址:https://www.cnblogs.com/nofind/p/12051558.html
Copyright © 2011-2022 走看看