记录编号 251511 评测结果 AAAAAAAAAA
题目名称 [SPOJ 220] 破译进攻计划 最终得分 100
用户昵称 Gravatarmikumikumi 是否通过 通过
代码语言 C++ 运行时间 8.811 s
提交时间 2016-04-18 07:54:26 内存使用 9.76 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int SIZEL=11000,SIZEN=20,SIZEM=300000+10,maxn=0x7fffffff/2;
int t,N,tot;
int len[SIZEN],sa[SIZEM],rank[SIZEM],height[SIZEM];
char text[SIZEM];
void read()
{
	tot=0;
	scanf("%d",&N);
	char str[SIZEL];
	len[0]=-1;
	//int cnt=maxn;
	for(int i=1;i<=N;i++)
	{
		scanf("%s",str);
		//cnt=min(cnt,(int)strlen(str));
		for(int j=0;j<strlen(str);j++)
			text[tot++]=str[j];
		len[i]=tot;
		text[tot++]='#';
	}
	tot--;
	//cout<<cnt<<endl;
}
int sum[SIZEM];
void basesort(int a[],int b[],int c[],int n,int m)
{
	for(int i=0;i<=m;i++) sum[i]=0;
	for(int i=0;i<n;i++) sum[b[a[i]]]++;
	for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
	for(int i=n-1;i>=0;i--) c[--sum[b[a[i]]]]=a[i];
}
int A[SIZEM],B[SIZEM];
int x[SIZEM],y[SIZEM];
void sortsuf(char text[],int sa[],int rank[],int n)
{
	for(int i=0;i<n;i++) A[i]=i,x[i]=text[i];
	//for(int i=0;i<n;i++) cout<<x[i]<<" ";
	//cout<<endl;
	basesort(A,x,sa,n,154);
	rank[sa[0]]=1;
	for(int i=1;i<n;i++)
	{
		if(x[sa[i]]==x[sa[i-1]]) rank[sa[i]]=rank[sa[i-1]];
		else rank[sa[i]]=rank[sa[i-1]]+1;
	}
	for(int k=1;k<=n;k<<=1)
	{
		for(int i=0;i<n;i++)
		{
			A[i]=i;
			x[i]=rank[i];
			if(i+k<n) y[i]=rank[i+k];
			else y[i]=0;
		}
		basesort(A,y,B,n,n);
		basesort(B,x,sa,n,n);
		rank[sa[0]]=1;
		for(int i=1;i<n;i++)
		{
			if(x[sa[i]]==x[sa[i-1]]&&y[sa[i]]==y[sa[i-1]]) rank[sa[i]]=rank[sa[i-1]];
			else rank[sa[i]]=rank[sa[i-1]]+1;
		}
	}
	for(int i=0;i<n;i++) rank[sa[i]]=i;
}
void make_height(int n)
{
	int h=0;
	for(int i=0;i<n;i++)
	{
		if(rank[i]==0) h=0;
		else
		{
			int k=sa[rank[i]-1];
			if(--h<0) h=0;
			while(text[i+h]==text[k+h]) h++;
		}
		height[rank[i]]=h;
	}
}
int mi[SIZEN]={0},ma[SIZEN]={0};
int ans=0;
bool check(int mid)
{
	int cnt=0;
	for(int i=0;i<=N;i++) mi[i]=maxn,ma[i]=0;
	for(int i=0;i<tot;i++)
	{
		if(height[i]>=mid)
		{
			for(int j=1;j<=N;j++)
			{
				if(sa[i]>len[j-1]&&sa[i]<len[j]) mi[j]=min(mi[j],sa[i]),ma[j]=max(ma[j],sa[i]);
				if(i>0&&sa[i-1]>len[j-1]&&sa[i-1]<len[j]) mi[j]=min(mi[j],sa[i-1]),ma[j]=max(ma[j],sa[i-1]);
			}
		}
		else
		{
			cnt=0;
			for(int j=1;j<=N;j++) if(ma[j]-mi[j]>=mid) cnt++;
			if(cnt==N) return 1;
			for(int j=1;j<=N;j++) ma[j]=-1,mi[j]=maxn;
		}
	}
	cnt=0;
	for(int j=1;j<=N;j++) if(ma[j]-mi[j]>=mid) cnt++;
	if(cnt==N) return 1;
	return 0;
}
void work()
{
	sortsuf(text,sa,rank,tot);
	make_height(tot);
	int l=0,r=tot;
	ans=0;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(check(mid)) l=mid+1,ans=mid;
		else r=mid;
	}
	//while(l>0&&!check(l)) l--;
	printf("%d\n",ans);
}
int main()
{
	freopen("RelevantPhrasesofAnnihil.in","r",stdin);
	freopen("RelevantPhrasesofAnnihil.out","w",stdout);
	scanf("%d",&t);
	while(t>0)
	{
		t--;
		//cout<<"arrive"<<endl;
		read();
		//..cout<<"arive"<<" "<<tot<<endl;endl;
		//cout<<text<<endl;
		work();
	}
	return 0;
}