1. 程式人生 > 其它 >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)