记录编号 479683 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [POI 2000] 最长公共子串 最终得分 100
用户昵称 GravatarShirry 是否通过 通过
代码语言 C++ 运行时间 0.038 s
提交时间 2017-12-22 23:19:32 内存使用 2.67 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
char s[maxn];
int n,w,x[maxn],y[maxn],b[maxn],c[maxn],sa[maxn],vis[10],height[maxn];
void get_sa(){
	int *rnk=x,*tp=y;
	int m=300;
	for(int i=1;i<=n;i++)tp[i]=s[i],rnk[i]=s[i];
	for(int i=1;i<=m;i++)c[i]=0;
	for(int i=1;i<=n;i++)c[tp[i]]++;
	for(int i=1;i<=m;i++)c[i]+=c[i-1];
	for(int i=n;i>=1;i--)sa[c[tp[i]]--]=i;
	for(int j=1;j<=n;j<<=1){
		int p=0;
		for(int i=n-j+1;i<=n;i++)tp[++p]=i;
		for(int i=1;i<=n;i++)if(sa[i]>j)tp[++p]=sa[i]-j;
		for(int i=0;i<=m;i++)c[i]=0;
		for(int i=1;i<=n;i++)c[rnk[tp[i]]]++;
		for(int i=1;i<=m;i++)c[i]+=c[i-1];
		for(int i=n;i>=1;i--)sa[c[rnk[tp[i]]]--]=tp[i];
		swap(rnk,tp);
		rnk[sa[1]]=1;
		p=1;
		for(int i=2;i<=n;i++){
			int O1=sa[i]+j>n?-1:tp[sa[i]+j];
			int O2=sa[i-1]+j>n?-1:tp[sa[i-1]+j];
			rnk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&O1==O2)?p:++p;
		}
		m=p;
		if(m>=n)break;
	}
}
void get_height(){
	int k=0,j;
	for(int i=1;i<=n;i++)x[sa[i]]=i;
	for(int i=1;i<=n;i++){
		if(k)k--;
		j=sa[x[i]-1];
		while(s[i+k]==s[j+k])k++;
		height[x[i]]=k;
	}
}
bool find(){
	for(int i=1;i<=w;i++)if(!vis[i])return 0;
	return 1;
}
bool check(int x){
	for(int i=1;i<=n;i++){
		if(height[i]>=x){
			vis[b[sa[i]]]=1;
			if(find())return 1;
		}
		else{
			memset(vis,0,sizeof(vis));
			vis[b[sa[i]]]=1;//和前面已匹配过的失配,从当前串开始
		}
	}
	return 0;
}
int main(){
	freopen("pow.in","r",stdin);
	freopen("pow.out","w",stdout);
	int len;
	scanf("%d",&w);
	for(int i=1;i<=w;i++){
		scanf("%s",s+n+1);
		len=strlen(s+1);
		for(int j=n+1;j<=len;j++)b[j]=i;
		n=len+1;
		s[n]='z'+i;
	}
	get_sa();get_height();
	int l=1,r=n+10,ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid))ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d\n",ans);
	return 0;
}