• 洛谷P2852 [USACO06DEC]牛奶模式Milk Patterns (Suffix Array)后缀数组


    前面后缀数组的板子相信大家都看得出来

    出现k次就相当于我们选择k个后缀,求LCP

    对于后缀i,j(rank[i]<rank[j])

    其LCP是 height(i+1~j)的最小值

    所以答案一定在rank连续的k个后缀中

    维护连续rank上k个后缀的LCP的最大值即可

    这个用单调队列就可以了= =

    理论上要离散化一下,虽然数据比较水,不离散也可以

    /*
    @Date    : 2019-07-18 21:34:03
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define RG register
    #define gi getint()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    IL int getint()
    {
    	RG int xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(ch<'0'|ch>'9')ch=='-'?f=1:f,ch=gc;
    	while(ch>='0'&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10,0);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int N=2e4+7;
    int a[N],b[N];
    int n,k;
    namespace SA{
    	int rkx[N],rky[N],cnt[N],*key1=rkx,*key2=rky,sa[N],rank[N];
    	int height[N];
    	int m;
    	inline void Qsort()
    	{
    		memset(cnt,0,sizeof cnt);
    		for(int i=1;i<=n;++i)++cnt[key1[i]];
    		for(int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
    		for(int i=n;i;--i)sa[cnt[key1[key2[i]]]--]=key2[i];
    	}
    /*
    	Attention:
    	sa -> address
    	rank -> rank
    	key1[i] ->key1[i]'s rank
    	key2[i] ->key2(rank)[i]'s address
    */
    	void getsa()
    	{
    		m=n;
    		for(int i=1;i<=n;++i)key1[i]=a[i],key2[i]=i;
    		Qsort();
    		for(int k=1,q=0;q<n;k<<=1)
    		{
    			q=0;
    			for(int i=n-k+1;i<=n;++i)key2[++q]=i;
    			for(int i=1;i<=n;++i)if(sa[i]>k)key2[++q]=sa[i]-k;
    			Qsort();
    			swap(key1,key2);
    			q=key1[sa[1]]=1;
    			for(int i=2;i<=n;++i)
    				key1[sa[i]]=(key2[sa[i-1]]==key2[sa[i]]&&
    					key2[sa[i-1]+k]==key2[sa[i]+k])?q:++q;
    			m=q;
    		}
    		for(int i=1;i<=n;++i)rank[sa[i]]=i;
    	}
    	inline void getheight()
    	{
    		int k=0;
    		for(int i=1;i<=n;++i)
    		{
    			if(k)--k;
    			int s=sa[rank[i]-1];
    			while(s+k<=n&&i+k<=n&&a[s+k]==a[i+k])++k;
    			height[rank[i]]=k;
    		}
    	}
    }
    using namespace SA;
    int main(void)
    {
    	#ifndef ONLINE_JUDGE
    	File("file");
    	#endif
    	n=gi,k=gi;
    	for(int i=1;i<=n;++i)b[i]=a[i]=gi;
    	sort(b+1,b+n+1);
    	int m=unique(b+1,b+n+1)-b-1;
    	for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
    	getsa();
    	getheight();
    	static int Q[1000100];
    	int ans=0;
    	int head=0,tail=-1;
    	--k;
    	for(int i=1;i<=n;++i)
    	{
    		while(head<=tail&&Q[head]+k<=i)++head;
    		while(head<=tail&&height[Q[tail]]>height[i])--tail;
    		Q[++tail]=i;
    		if(i>=k)ans=max(ans,height[Q[head]]);
    	}
    	printf("%d",ans); 	
    	return 0;
    }
    
  • 相关阅读:
    bzoj 3238
    bzoj 3473 后缀自动机多字符串的子串处理方法
    bzoj 2998 第k小字串
    bzoj 3672 利用点分治将CDQ分治推广到树型结构上
    bzoj 3671 贪心
    NOIP模拟题——nan
    NOIP模拟题——kun(栈)
    hduP2586——How far away ?
    DP习题
    NOIP模拟题——来自风平浪静的明天
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11211493.html
Copyright © 2020-2023  润新知