Codeforces1537 E2. Erase and Extend (Hard Version)(lcp)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1537 E2. Erase and Extend (Hard Version)(lcp)相关的知识,希望对你有一定的参考价值。
题意:
解法:
显然s[1]一定会被作为开头.
容易想到正着选,如果s[i]<s[1],那么一定就选上,
如果s[i]>s[1],那么一定不选,break.
如果s[i]=s[1],需要讨论选不选.
这样选出的前缀一定都是<=s[1]的,假设选了s[1,pos],循环输出k的长度就是答案.
s[i]=s[1]时怎么判断是否选呢?
求出s[1,n]和s[i,n]的lcp,
1.如果lcp<n-i+1,那么比较s[1+lcp]和s[i+lcp],如果s[i+lcp]<s[1+lcp]则选.
2.如果lcp=n-i+1,那么不选,因为此时s[i+lcp]相当于s[1],s[1]一定是>=s[1+lcp]的.
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=2e6+5;
const int mod=1e9+7;
const int p=1331;
int base[maxm];
int h[maxm];
char s[maxm];
int n,k;
int get(int l,int r){
return ((h[r]-base[r-l+1]*h[l-1])%mod+mod)%mod;
}
int check(int x){
int l=1,r=n-x+1;
int ans=0;
while(l<=r){
int mid=(l+r)/2;
int lc=get(1,1+mid-1);
int rc=get(x,x+mid-1);
if(lc==rc){
ans=mid,l=mid+1;
}else{
r=mid-1;
}
}
if(ans==n-x+1)return 0;
return s[x+ans]<s[1+ans];
}
void solve(){
cin>>n>>k;
cin>>(s+1);
base[0]=1;
for(int i=1;i<=n;i++){
h[i]=(h[i-1]*p+s[i])%mod;
base[i]=base[i-1]*p%mod;
}
int pos=1;
for(int i=2;i<=n;i++){
if(s[i]>s[1])break;
else if(s[i]==s[1]){
if(check(i)){
pos=i;
}else{
break;
}
}else{
pos=i;
}
}
int cur=1;
for(int i=1;i<=k;i++){
cout<<s[cur];
cur++;
if(cur==pos+1)cur=1;
}
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
solve();
return 0;
}
以上是关于Codeforces1537 E2. Erase and Extend (Hard Version)(lcp)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces1537 F. Figure Fixing(思维,二分图染色)
Codeforces 1303E - Erase Subsequences
codeforces 391E2 (Codeforces Rockethon 2014E2)