社区讨论

后缀数组求助,来位大佬舅舅蒟蒻吧

SP220PHRASES - Relevant Phrases of Annihilation参与者 4已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@mi7rhihf
此快照首次捕获于
2025/11/21 02:25
4 个月前
此快照最后确认于
2025/11/21 02:25
4 个月前
查看原帖
CPP
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
int n,c;
int fir[N],sec[N],rnk[N],t[N],sa[N],b[N];
void msort(){
	memset(t,0,sizeof t);
	for(int i=1;i<=n;++i)t[sec[i]]++;
	for(int i=1;i<N;++i)t[i]+=t[i-1];
	for(int i=n;i;--i)b[t[sec[i]]--]=i;
	memset(t,0,sizeof t);
	for(int i=1;i<=n;++i)t[fir[b[i]]]++;
	for(int i=1;i<N;++i)t[i]+=t[i-1];
	for(int i=n;i;--i)sa[t[fir[b[i]]]--]=b[i];
}
int height[N];
void get_height(char *s){
	memset(height,0,sizeof height);
	int k=0;
	for(int i=1;i<=n;++i){
		if(rnk[i]==1){
		    height[i]=0;
		    continue;
	    }
		if(k)--k;
	    int j=sa[rnk[i]-1];
	    while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
	    height[i]=k;
	}
}
void get_sa(char *s){
	for(int i=1;i<=n;++i)rnk[i]=s[i];
	for(int k=1;k<=n;k*=2){
		for(int i=1;i<=n;++i){
			fir[i]=rnk[i];
			if(i+k>n)sec[i]=0;
			else sec[i]=rnk[i+k];
		}
		msort();
		int num=1;rnk[sa[1]]=1;
		for(int i=2;i<=n;++i){
			if(fir[sa[i]]!=fir[sa[i-1]]||sec[sa[i]]!=sec[sa[i-1]])num++;
			rnk[sa[i]]=num;
		}
		if(num==n)break;
	}	
}
char s[N];
int l[15],r[15],mx[15],mn[15];
bool check(int x){
	memset(mx,0,sizeof mx);
	memset(mn,0x3f,sizeof mn);
	int bo=0,js=0;
	for(int i=1;i<=n;++i){
		if(!(height[sa[i]]>=x)){
			if(js>=2*c){
//				cout<<x<<":";for(int j=1;j<=c;++j)cout<<"("<<mn[j]<<","<<mx[j]<<")";puts("");
				bo=1;
				for(int j=1;j<=c;++j){
					if(mx[j]-mn[j]<x)bo=0;
				}
				if(bo)return 1;
			}js=0;
			memset(mx,0,sizeof mx);
			memset(mn,0x3f,sizeof mn);
		}
		js++;
		for(int j=1;j<=c;++j){
			if(l[j]<=sa[i]&&sa[i]<=r[j]){
				mn[j]=min(mn[j],sa[i]);
				mx[j]=max(mx[j],sa[i]);
				break;
			}
		}
	}  
	bo=1;
	for(int i=1;i<=c;++i){
		if(mx[i]-mn[i]+1<x)bo=0;
	}
	if(bo)return 1;
	return 0;
}
int main(){
//	freopen("1.in","r",stdin);
//	freopen("my.out","w",stdout);
	int t;
	cin>>t;
	while(t--){
		scanf("%d",&c);
		int now=1;
		for(int i=1;i<=c;++i){
			l[i]=now;
			scanf("%s",s+now);
			now=strlen(s+1);
			r[i]=now;
			s[++now]=c;
			++now;
		}
		n=strlen(s+1);
		get_sa(s);
		get_height(s);
//		for(int i=1;i<=n;++i)printf("(%d,%d,%d)\n",sa[i],i,height[sa[i]]);
		int l=0,r=n,ans=0;
		while(l<r){
			int mid=l+(r-l)/2;
			if(check(mid))ans=mid,l=mid+1;
			else r=mid;
		}
		printf("%d\n",ans);
	}
}

回复

8 条回复,欢迎继续交流。

正在加载回复...