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

思路:
先从第二个字母开始遍历,与第一个字母比较,若大则直接标记上然后break,若相等则以两个相同字母开始,向后比较,直到出现不等为止,然后分类处理,详见code。

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;
}

猜你喜欢

转载自blog.csdn.net/m0_51270992/article/details/118036990
今日推荐