Codeforces 940 C. Phone Numbers

C. Phone Numbers
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
And where the are the phone numbers?

You are given a string s consisting of lowercase English letters and an integer k. Find the lexicographically smallest string t of length k, such that its set of letters is a subset of the set of letters of s and s is lexicographically smaller than t.

It’s guaranteed that the answer exists.

Note that the set of letters is a set, not a multiset. For example, the set of letters of abadaba is {a, b, d}.

String p is lexicographically smaller than string q, if p is a prefix of q, is not equal to q or there exists i, such that pi < qi and for all j < i it is satisfied that pj = qj. For example, abc is lexicographically smaller than abcd , abd is lexicographically smaller than abec, afa is not lexicographically smaller than ab and a is not lexicographically smaller than a.

Input
The first line of input contains two space separated integers n and k (1 ≤ n, k ≤ 100 000) — the length of s and the required length of t.

The second line of input contains the string s consisting of n lowercase English letters.

Output
Output the string t conforming to the requirements above.

It’s guaranteed that the answer exists.

Examples
inputCopy
3 3
abc
outputCopy
aca
inputCopy
3 2
abc
outputCopy
ac
inputCopy
3 3
ayy
outputCopy
yaa
inputCopy
2 3
ba
outputCopy
baa
Note
In the first example the list of strings t of length 3, such that the set of letters of t is a subset of letters of s is as follows: aaa, aab, aac, aba, abb, abc, aca, acb, … Among them, those are lexicographically greater than abc: aca, acb, … Out of those the lexicographically smallest is aca.

题意:给你一个序列s,用它里面的字母集合,构成一个新的序列,使它大于s,且是最小的
如例子
3 3
abc
你可以用abc这三个字母构成长度为3的序列有 aaa, aab, aac, aba, abb, abc, aca, acb, acc,…
其中大于abc的有 aca acb acc…
最小的是aca
所以输出aca

思路:
先设mn为s字符串中最小的字符,mx为是字符串中最大的字符,gz[26]为s字符串对用的集合
一共就两种情况:
第一种: 如果k>n,很显然先输出s,然后再输出n-k个mn就可以了
第二种:k<=n 那么只要从k位置开始,如果它是mx,那么它肯定要改变,所以只要把末尾最大的字符串去掉,假设去掉了长度为i,那么1至i-1直接输出就可以了,接下来只要在gz[26]找到比s[i]大的第一个字符输出,然后再输出n-i-1个mn就可以了。
一个类似贪心的构造题,自己构造的字符串与s字符串相似的越多,字符串越小

#include<bits/stdc++.h>
#define LL long long
#define Max 100005
const LL mod=1e9+7;
const LL LL_MAX=9223372036854775807;
using namespace std;
int n,k;
char a[Max],gz[26];
char mn='z',mx='a';
int m[26];
int main()
{
    int len=0;
    scanf("%d%d%s",&n,&k,a);
    for(int i=0; a[i]; i++)
    {
        if(!m[a[i]-'a'])
        {
            gz[len++]=a[i];
            m[a[i]-'a']=1;
            mn=min(a[i],mn);
            mx=max(a[i],mx);
        }
    }
    sort(gz,gz+len);
    if(k>n){
       printf("%s",a);
       for(int i=n;i<k;i++)
            printf("%c",mn);
    }else{
        int i=k-1;
        while(a[i]==mx)
            i--;
       // printf("%d\n",i);
        for(int j=0;j<i;j++)
            printf("%c",a[j]);
        int j=0;
        while(a[i]>=gz[j])
            j++;
        printf("%c",gz[j]);
        for(int j=i+1;j<k;j++)
            printf("%c",mn);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值