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