其他分享
首页 > 其他分享> > HZNU训练补题记录

HZNU训练补题记录

作者:互联网

[https://codeforces.com/group/DOZ49JViPG/contest/353311/problem/L](L. Lengths and Periods)

题意:给你一个字符串,问 最长循环串/循环节 最大为多少

解析:实际上就是求 i 位到末尾与 j 位到末尾的字符串的最长公共前缀除以 j-i+1
我们可以将原串翻转,lcp实际上就是两个节点的LCA,实际上即是某点的所有endpos,在一个endpos集中明显相邻最小,贡献为 某点长度/(j-i+1)
利用set维护endpos集合转移取min即可,注意set维护endpos集合的写法

#include <bits/stdc++.h>
const int maxn=4e5+50;
using namespace std;
typedef long long ll;
int head[maxn],nex[maxn],to[maxn],ecnt;
int size[maxn];
set<int>st[maxn];
string s;
int ord[maxn];
int pr[maxn];
int mi[maxn];
const int inf=0x3f3f3f3f;
struct node {
	int ch[26];
	int len;
	int fa;
} a[maxn<<1];
int pre=1,tot=1;
inline void add(int x,int y) {
	to[++ecnt]=y;
	nex[ecnt]=head[x];
	head[x]=ecnt;
}
inline void init() {
	pre=tot=1;
	for(int i=0; i<26; i++) {
		a[1].ch[i]=0;
	}
	a[1].len=0;
	a[1].fa=0;
}
inline int newnode() {
	++tot;
	a[tot].len=0;
	a[tot].fa=0;
	for(int i=0; i<26; i++) {
		a[tot].ch[i]=0;
	}
	return tot;
}
inline int insert(int c) {
	int p=pre,np=pre=newnode();
	size[tot]=1;
	a[np].len=a[p].len+1;
	for(; p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np;
	if(!p) a[np].fa=1;
	else {
		int q=a[p].ch[c];
		if(a[q].len==a[p].len+1) a[np].fa=q;
		else {
			int nq=newnode();
			a[nq]=a[q];
			a[nq].len=a[p].len+1;
			a[q].fa=a[np].fa=nq;
			for(; p&&a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq;
		}
	}
	return pre;
}
inline int gcd(int a,int b) {
	return b==0?a:gcd(b,a%b);
}
signed main() {
	ios::sync_with_stdio(false);
	cin>>s;
	reverse(s.begin(),s.end());
	int len=s.length();
	for(int i=0; i<len; i++) {
		int p=insert(s[i]-'a');
		st[p].insert(i+1);
	}
	int pos=1;
	for(int i=0; i<len; i++) {
		pos=a[pos].ch[s[i]-'a'];
		pr[i+1]=pos;
	}
	for(int i=2; i<=tot; i++) {
		add(a[i].fa,i);
		ord[i]=i;
		mi[i]=inf;
	}
	mi[1]=inf;
	ord[1]=1;
	sort(ord+1,ord+1+tot,[](int x,int y) {
		return a[x].len>a[y].len;
	});
	int f=0,fz=0,fm=1,cnt=0;
	for(int k=1; k<=tot; k++) {
		int x=ord[k];
		if(x==1)continue;
		for(int i=head[x]; i; i=nex[i]) {
			int y=to[i];
			mi[x]=min(mi[x],mi[y]);
			if(st[y].empty())continue;
			if(st[x].empty()) {
				swap(st[x],st[y]);
				continue;
			}
			auto &L=st[x],&R=st[y];
			if(L.size()<R.size())swap(L,R);
			for(auto it:R) {
				set<int>::iterator it1;
				set<int>::iterator it2;
				it1=st[x].upper_bound(it);
				if(it1==st[x].begin()) {
					mi[x]=min(mi[x],*it1-it);
				} else if(it1==st[x].end()&&st[x].size()) {
					mi[x]=min(mi[x],it-*(st[x].begin()));
				} else if(st[x].size()) {
					it2=it1;
					it1--;
					mi[x]=min(mi[x],it-*it1);
					mi[x]=min(mi[x],*it2-it);
				}
				st[x].insert(it);
			}
			if(st[x].size()<2)continue;
			int fx=a[x].len;
			int fy=mi[x];
			if(!f&&fx&&fy) {
				fz=fx;
				fm=fy;
				f=1;
			} else {
				if(1ll*fz*fy<1ll*fm*fx) {
					fz=fx;
					fm=fy;
				}
			}
		}
	}
	fz=fz+fm;
	int gz=gcd(fz,fm);
	fz/=gz;
	fm/=gz;
	cout<<fz<<"/"<<fm<<'\n';
}

[https://codeforces.com/group/DOZ49JViPG/contest/353825/problem/B](B. Beautiful Words)

标签:训练,min,int,HZNU,mi,st,maxn,补题,it1
来源: https://www.cnblogs.com/ddsszdnt/p/15541984.html