2018.12.01【SPOJ220】Relevant Phrases of Annihilation(后缀数组)(二分答案)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/84673259

传送门


解析:

套路题。

首先串成一串求一下SA。

然后按照二分出的 l e n len ,根据 h e i g h t height 数组分组。

在每组里面看 k k 个串是否分别满足条件就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

cs int N=100005;
namespace SA{
	char s[N];
	int sa[N],rk[N],ht[N],len;
	int bin[N];
	inline void radix_sort(int *cs x,int *cs y,int m,int n);
	inline void init();
	inline bool check(int x);
}

inline void SA::radix_sort(int *cs x,int *cs y,int m,int n){
	memset(bin+1,0,sizeof(int)*m);
	for(int re i=1;i<=n;++i)++bin[x[i]];
	for(int re i=1;i<=m;++i)bin[i]+=bin[i-1];
	for(int re i=n;i;--i)sa[bin[x[y[i]]]--]=y[i];
}

inline void SA::init(){
	int *x=rk,*y=ht,n=len,m=256;
	for(int re i=1;i<=n;++i)x[i]=s[i],y[i]=i;
	radix_sort(x,y,m,n);
	for(int re i=1,cnt=0;i<=n&&cnt<n;i<<=1){
		cnt=0;
		for(int re j=n-i+1;j<=n;++j)y[++cnt]=j;
		for(int re j=1;j<=n;++j)if(sa[j]>i)y[++cnt]=sa[j]-i;
		radix_sort(x,y,m,n);
		swap(x,y);
		x[sa[1]]=cnt=1;
		for(int re j=2;j<=n;++j)x[sa[j]]=((y[sa[j]]==y[sa[j-1]])&&(y[sa[j]+i]==y[sa[j-1]+i])?cnt:++cnt);
		m=cnt;
	}
	for(int re i=1;i<=n;++i)rk[sa[i]]=i;
	for(int re i=1,k=0,j;i<=len;ht[rk[i++]]=k)
	for(k?--k:0,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
}

int be[12],k;
int l[12],id[N];
int maxn[12],minn[12];

inline bool SA::check(int x){
	fill(maxn+1,maxn+k+1,0);
	fill(minn+1,minn+k+1,N);
	for(int re i=1;i<=len;++i){
		if(ht[i]<x){
			fill(maxn+1,maxn+k+1,0);
			fill(minn+1,minn+k+1,N);
			maxn[id[sa[i]]]=sa[i];
			minn[id[sa[i]]]=sa[i];
		}
		else{
			maxn[id[sa[i]]]=max(maxn[id[sa[i]]],sa[i]);
			minn[id[sa[i]]]=min(minn[id[sa[i]]],sa[i]);
			maxn[id[sa[i-1]]]=max(maxn[id[sa[i-1]]],sa[i-1]);
			minn[id[sa[i-1]]]=min(minn[id[sa[i-1]]],sa[i-1]);
			for(int re j=1;j<=k;++j){
				if(maxn[j]-minn[j]<x)break;
				if(j==k)return true;
			}
		}
	}
	return false;
}

int T;
signed main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&k);SA::len=0;
		memset(SA::s,0,sizeof SA::s);
		for(int re i=1;i<=k;++i){
			SA::len++;
			scanf("%s",SA::s+SA::len);
			be[i]=SA::len;
			SA::len+=(l[i]=strlen(SA::s+SA::len));
			for(int re j=be[i];j<SA::len;++j){
				id[j]=i;
			}
			SA::s[SA::len]='$'+i;
		}
		SA::init();
		re int l=0,r=10000;
		while(l<r){
			int mid=(l+r+1)>>1;
			if(SA::check(mid))l=mid;
			else r=mid-1;
		}
		printf("%d\n",l);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/84673259
今日推荐