zoukankan      html  css  js  c++  java
  • 【洛谷2852】[USACO06DEC] Milk Patterns G(重拾后缀数组)

    点此看题面

    • 给定一个长度为(n)的序列。
    • 求出最长的出现至少(k)次的子串的长度。
    • (nle2 imes10^4)

    (Height)数组

    考虑二分答案(x),则存在一个出现(k)次、长度为(x)的子串,等价于存在(k)个串的(LCP)长度大于等于(x)

    贪心地考虑,必然选择排名连续的(k)个串。

    根据(SA)(Height)数组的性质,([l,r])(LCP)长度就是(min_{i=l+1}^rHeight_i)

    所以就是要判断是否存在连续(k-1)(Height_i)全都大于等于(x)

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 20000
    #define V 1000000
    using namespace std;
    int n,k,a[N+5];
    class SuffxArray
    {
    	private:
    		int SA[N+5],H[N+5],p[N+5],rk[N+5],t[V+5];
    		I void Sort(CI S)
    		{
    			RI i;for(i=1;i<=S;++i) t[i]=0;for(i=1;i<=n;++i) ++t[rk[i]];
    			for(i=1;i<=S;++i) t[i]+=t[i-1];for(i=n;i;--i) SA[t[rk[p[i]]]--]=p[i];
    		}
    	public:
    		I void Init(CI n,int *a)//初始化
    		{
    			RI i,j,k;for(i=1;i<=n;++i) rk[p[i]=i]=a[i];
    			RI t=0,S=V;for(Sort(S),k=1;t^n;k<<=1,S=t)//倍增预处理SA数组
    			{
    				for(i=1;i<=k;++i) p[i]=n-k+i;for(t=k,i=1;i<=n;++i) SA[i]>k&&(p[++t]=SA[i]-k);//按照第二维大小确定顺序
    				for(Sort(S),i=1;i<=n;++i) p[i]=rk[i];for(rk[SA[1]]=t=1,i=2;i<=n;++i)
    					(p[SA[i]]^p[SA[i-1]]||p[SA[i]+k]^p[SA[i-1]+k])&&++t,rk[SA[i]]=t;//求出新的排名
    			}
    			for(k=0,i=1;i<=n;++i) rk[SA[i]]=i;for(i=1;i<=n;++i)//预处理Height数组
    			{
    				if(k&&--k,rk[i]==1) continue;j=SA[rk[i]-1];//延续上一次的答案
    				W(i+k<=n&&j+k<=n&&a[i+k]==a[j+k]) ++k;H[rk[i]]=k;//向外扩展
    			}
    		}
    		I bool Check(CI x) {RI i,t=1;for(i=1;i<=n&&t<k;++i) H[i]>=x?++t:(t=1);return t==k;}//验证是否存在连续k-1位
    }S;
    int main()
    {
    	RI i;for(scanf("%d%d",&n,&k),i=1;i<=n;++i) scanf("%d",a+i);
    	S.Init(n,a);RI l=0,r=n,mid;W(l<r) S.Check(mid=l+r+1>>1)?l=mid:r=mid-1;//二分答案
    	return printf("%d
    ",l),0;
    }
    
  • 相关阅读:
    idea的使用和安装破解 2019.2
    get请求和post请求的区别
    MySQL-事务
    MySQL-mysql的查询练习
    MySQL-mysql的多表查询
    CodeForces
    2018宁夏邀请赛网赛 I. Reversion Count(java练习题)
    HDU
    Codeforces Round #479 (Div. 3)解题报告
    nyoj 1274信道安全 第九届河南省赛(SPFA)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu2852.html
Copyright © 2011-2022 走看看