建议加强数据
查看原帖
建议加强数据
377760
Reunite楼主2025/1/27 18:11

写了一个 n2n^2 的假启发式合并也过了,跑的还比我 2logn2\log n 的快。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;

int n,tot=1,K,L,P;
char c[50005];
int fa[100005];
int len[100005];
int mp[100005][2];
set <int> st[100005];
vector <int> g[100005];

inline int ins(int c,int las){
	if(mp[las][c]){
		int p=las,v=mp[p][c];
		if(len[p]+1==len[v]) return v;
		int x=++tot;
		len[x]=len[p]+1;
		for(int i:{0,1}) mp[x][i]=mp[v][i];
		while(mp[p][c]==v) mp[p][c]=x,p=fa[p];
		fa[x]=fa[v],fa[v]=x;
		return x;
	}
	int x=++tot,p=las;
	len[x]=len[p]+1;
	while(p&&!mp[p][c]) mp[p][c]=x,p=fa[p];
	if(!p) fa[x]=1;
	else{
		int v=mp[p][c];
		if(len[p]+1==len[v]) fa[x]=v;
		else{
			int y=++tot;
			len[y]=len[p]+1;
			for(int i:{0,1}) mp[y][i]=mp[v][i];
			while(mp[p][c]==v) mp[p][c]=y,p=fa[p];
			fa[y]=fa[v],fa[x]=fa[v]=y;
		}
	}
	return x;
}

inline void in(int &n){
	n=0;
	char c=getchar();
	while(c<'0' || c>'9') c=getchar();
	while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
	return ;
}

inline void solve(int u){
	for(int v:g[u]){
		solve(v);
		if(st[u].size()>st[v].size()) swap(st[u],st[v]);
		for(int v:st[v]) st[u].insert(v);
	}
	// printf("%d:%d\n",u,st[u].size());
	if(st[u].size()<2) return ;
	auto it=st[u].begin();
	int mn=1e9,pos=0;
	while(it!=st[u].end()){
		if(it!=st[u].begin()){
			int x=*it-*prev(it);
			if(x<mn) mn=x,pos=*prev(it);
		}
		if(next(it)!=st[u].end()){
			int x=*next(it)-*it;
			if(x<mn) mn=x,pos=*it;
		}
		it++;
	}
	if(K<len[u]/mn+1){
		K=len[u]/mn+1;
		L=mn;
		P=pos-len[u]+1;
	}
	return ;
}

int main(){
	in(n);
	for(int i=1;i<=n;i++){
		char ch[3];
		scanf("%s",ch+1);
		c[i]=ch[1];
	}
	int las=1;
	for(int i=1;i<=n;i++) las=ins(c[i]-'a',las),st[las].insert(i);
	for(int i=2;i<=tot;i++) g[fa[i]].emplace_back(i);
	solve(1);
	printf("%d\n%d\n%d\n",K,L,P);

	return 0;
}
2025/1/27 18:11
加载中...