2018.11.24 poj3261Milk Patterns(后缀数组)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/84440859

传送门
后缀数组经典题。


貌似可以用二分答案+后缀数组?
我自己 y y yy 了一个好写一点的方法。
直接先预处理出 h e i g h t height 数组。
然后对于所有连续的 k 1 k-1 h e i g h t height 的最小值取最大值即可。
代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=2e5+5;
int n,m,sig,k,sa[N],sa2[N],rk[N],a[N],val[N],st[N][16],ans=0,Log[N],ht[N];
inline void Sort(){
	static int cnt[N];
	for(ri i=1;i<=m;++i)cnt[i]=0;
	for(ri i=1;i<=n;++i)++cnt[rk[i]];
	for(ri i=2;i<=m;++i)cnt[i]+=cnt[i-1];
	for(ri i=n;i;--i)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void getsa(){
	for(ri i=1;i<=n;++i)rk[i]=lower_bound(val+1,val+sig+1,a[i])-val,sa2[i]=i;
	m=sig,Sort();
	for(ri w=1,p=0;m!=n;w<<=1,p=0){
		for(ri i=n-w+1;i<=n;++i)sa2[++p]=i;
		for(ri i=1;i<=n;++i)if(sa[i]>w)sa2[++p]=sa[i]-w;
		Sort(),swap(sa2,rk),rk[sa[1]]=p=1;
		for(ri i=2;i<=n;++i)rk[sa[i]]=(sa2[sa[i]]==sa2[sa[i-1]]&&sa2[sa[i]+w]==sa2[sa[i-1]+w])?p:++p;
		m=p;
	}
	for(ri i=1,j,k=0;i<=n;ht[rk[i++]]=k)for(k?--k:k,j=sa[rk[i]-1];a[i+k]==a[j+k];++k);
	for(ri i=1;i<=n;++i)st[i][0]=ht[i];
	for(ri j=1;j<=15;++j)for(ri i=1;i+(1<<j)<=n;++i)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
inline int rmq(int l,int r){return min(st[l][Log[r-l+1]],st[r-(1<<Log[r-l+1])+1][Log[r-l+1]]);}
int main(){
	n=read(),k=read(),Log[0]=-1;
	for(ri i=1;i<=n;++i)val[i]=a[i]=read(),Log[i]=Log[i>>1]+1;
	sort(val+1,val+n+1),sig=unique(val+1,val+n+1)-val-1;
	getsa();
	for(int l=1,r=k-1;r<=n;++l,++r)ans=max(ans,rmq(l,r));
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/84440859