其他分享
首页 > 其他分享> > [luogu] P2463 [SDOI2008]Sandy的卡片

[luogu] P2463 [SDOI2008]Sandy的卡片

作者:互联网

把串连起来就好了,但是中间要加分隔符(极大值且递增)。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;const int N=1e6+7,INF=0x7fffffff;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9')	{if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')	{x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}



int n,m,s[N],x[N],y[N],c[N],sa[N],rk[N],height[N];
int len[N],a[1005][1005],id[N],l,r,minn,maxx;
int num,top,vis[N],stack[N];
inline void get_SA()
{
	for(int i=1;i<=n;i++) c[x[i]=s[i]]++;
	for(int i=1;i<=m;i++) c[i]+=c[i-1];
	for(int i=n;i>=1;i--) sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1)
	{
		int num1=0;
		for(int i=n-k+1;i<=n;i++) y[++num1]=i;
		for(int i=1;i<=n;i++) if(sa[i]>k) y[++num1]=sa[i]-k;
		for(int i=1;i<=m;i++) c[i]=0;
		for(int i=1;i<=n;i++) c[x[i]]++;
		for(int i=1;i<=m;i++) c[i]+=c[i-1];
		for(int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
		swap(x,y);x[sa[1]]=1;num1=1;
		for(int i=2;i<=n;i++)
			x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) ? num1:++num1;
		if(num1==n) break;m=num1;
	}
}
inline void get_Height()
{
	for(int i=1;i<=n;i++) rk[sa[i]]=i;
	for(int i=1,k=0;i<=n;i++)
	{
		if(rk[i]==1) continue;
		if(k) k--;int j=sa[rk[i]-1];
		while(s[i+k]==s[j+k]) k++;
		height[rk[i]]=k;
	}
}
inline bool check(int x)
{
	while(top) vis[stack[top--]]=0;
	for(int i=1;i<=n;i++)
	{
		if(height[i]<x)
			while(top) vis[stack[top--]]=0;
		if(!vis[id[sa[i]]])
		{
			vis[id[sa[i]]]=1;
			stack[++top]=id[sa[i]];
			if(top==num) return 1;
		}
	}return 0;
}
int main()
{
	num=read();r=minn=INF;
	for(int i=1;i<=num;i++)
	{
		len[i]=read();
		for(int j=1;j<=len[i];j++)
		{
			a[i][j]=read();
			if(j!=1) maxx=max(maxx,a[i][j]-a[i][j-1]);
		}r=min(r,len[i]-1);
	}
	for(int i=1;i<=num;i++)
	{
		for(int j=2;j<=len[i];j++)
		{
			s[++n]=a[i][j]-a[i][j-1];
			id[n]=i;minn=min(minn,s[n]);
		}s[++n]=++maxx;
	}
	for(int i=1;i<=n;i++) s[i]=s[i]-minn+1,m=max(m,s[i]);
	get_SA();get_Height();
	int ans=0;while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid)) l=mid+1,ans=mid;
		else r=mid-1;
	}cout<<ans+1<<endl;
	return 0;
}

标签:ch,num1,int,luogu,mid,include,sa,SDOI2008,Sandy
来源: https://www.cnblogs.com/chtomede/p/12095420.html