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)

Codeforces1303E. Erase Subsequences

CodeForces - 1251E2 (思维+贪心)

codeforces#1251E2. Voting (Hard Version)(贪心)