HZNU訓練補題記錄
阿新 • • 發佈:2021-11-11
[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)