Codeforces Round #726 (Div. 2) E.Erase and Extend (Hard Version)

Problem:
This is the hard version of the problem. The only difference is the constraints on n and k. You can make hacks only if all versions of the problem are solved.
You have a string s, and you can do two types of operations on it:

Delete the last character of the string.
Duplicate the string: s:=s+s

, where +

denotes concatenation. 

You can use each operation any number of times (possibly none).

Your task is to find the lexicographically smallest string of length exactly k that can be obtained by doing these operations on string s.

A string ais lexicographically smaller than a string b

if and only if one of the following holds: a is a prefix of b, but a≠b;
In the first position where a
and b differ, the string a has a letter that appears earlier in the alphabet than the corresponding letter in b.

Input
The first line contains two integers n, k (1≤n,k≤5⋅105) — the length of the original string sand the length of the desired string.
The second line contains the string s, consisting of n lowercase English letters.

Output
Print the lexicographically smallest string of length k
that can be obtained by doing the operations on string s.

Example

Input
8 16
dbcadabc

Output
dbcadabcdbcadabc

Input
4 5
abcd

Output
aaaaa

Idea:
Start traversing from the second letter first, compare it with the first letter, if it is large, mark it directly and then break, if it is equal, start with two identical letters, compare backwards until there is an inequality, and then classify and process , see code for details.

code:

#include <bits/stdc++.h>
#define DEBUG freopen("_in.txt", "r", stdin);
// #define DEBUG freopen("_in.txt", "r", stdin),freopen("_out.txt", "w", stdout);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll maxn = 5e5 + 10;
const ll maxm = maxn * maxn;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 2147493647;

ll t, n, m, k;
char str[maxn], str1[maxn];

int main()
{
    
    
    // DEBUG;
    scanf("%lld%lld", &n, &k);
    scanf("%s", str + 1);
    ll pos=0;
    ll i=2;
    while (i<=n)
    {
    
    
        if (str[i] > str[1])
        {
    
    
            pos = i-1;
            break;
        }
        else if (str[i] == str[1])
        {
    
    
            ll j = 1, num = i;
            while (i<=n&& j < num&&str[i] == str[j] )
            {
    
    
                i++;//这里i比j小了,就一定比第一个小,保证O(n)
                j++;
            }
            if(i>n)
            {
    
    
                pos = num-1;
                break;
            }
            if (j == num)
                continue;
            if(str[i]<str[j]) continue;
            pos = num-1;
            break;
        }
        else
        {
    
    
            i++;
        }
    }
    if(pos==0)
    {
    
    
        pos=n;
    }
    for (ll i = 1; i <= k; i++)
    {
    
    
        if (i % pos != 0)
            printf("%c", str[i % pos]);
        else
            printf("%c", str[pos]);
    }
    printf("\n");
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_51270992/article/details/118036990