Codeforces Round #350 (Div. 2) F. Restore a Number(有一位数为n的数,在后面添上n这个数,然后将所有的数字打乱输出,再给你一串原数字的子串,输出最小)

F. Restore a Number
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Vasya decided to pass a very large integer n to Kate. First, he wrote that number as a string, then he appended to the right integer k — the number of digits in n.

Magically, all the numbers were shuffled in arbitrary order while this note was passed to Kate. The only thing that Vasya remembers, is a non-empty substring of n (a substring of n is a sequence of consecutive digits of the number n).

Vasya knows that there may be more than one way to restore the number n. Your task is to find the smallest possible initial integer n. Note that decimal representation of number n contained no leading zeroes, except the case the integer n was equal to zero itself (in this case a single digit 0 was used).

Input

The first line of the input contains the string received by Kate. The number of digits in this string does not exceed 1 000 000.

The second line contains the substring of n which Vasya remembers. This string can contain leading zeroes.

It is guaranteed that the input data is correct, and the answer always exists.

Output

Print the smalles integer n which Vasya could pass to Kate.

Examples
input
003512
021
output
30021
input
199966633300
63
output

题意:有一位数为n的数,在后面添上n这个数,然后将所有的数字打乱输出,再给你一串原来数字的子串,输出符合条件的数且使它的值最小


思路:因为原来的数字的长度是小于等于1000000,所以我们可以枚举它的长度是几位数的,而且这个数的长度是唯一的
那么我们可以得到去除了它的长度和子串之后的数字还剩下哪些数字
那么原来的子串的组成形式可能有一下几种
1.子串是以0开头的,那么一定是先输出剩下数字中一位最小的且不为0的数,然后把剩下的数字中为0的输出,然后输出子串,再输出剩下的串
2.如果该子串不以0开头,那么输出的子串可能有一下两种形式
分别是子串在前面和子串在中间,分别构造出这两种数进行比较输出较小的(如果相同,输出任意一组均可)
需要特判的是剩下的数是否全部为0


#include<bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
const int maxn=1001000;
char s1[maxn],s2[maxn],s3[maxn];
int num[10],P[10],d[maxn],NUM1[2*maxn],NUM2[2*maxn];
int a[maxn];

int main(){
    P[0]=0,P[1]=10;
    for(int i=2;i<=7;i++)
        P[i]=P[i-1]*10;
    scanf("%s%s",s1,s2);
    int cnt1=0;
    int len1=strlen(s1),len2=strlen(s2);
    for(int i=0;i<len2;i++){
        num[s2[i]-'0']++;
        d[++cnt1]=s2[i]-'0';
    }
    for(int i=0;i<len1;i++){
        int c=s1[i]-'0';
        num[c]--;
    }
    for(int i=0;i<=7;i++){
        if(len1-(i+1)<P[i+1]&&len1-(i+1)>=P[i]){
            int c=len1-(i+1);
            while(c>0){
                int b=c%10;
                c/=10;
                num[b]++;
            }
            int cnt=0,flag1=0,id=0;
            for(int j=0;j<=9;j++){
                 while(num[j]<0){
                    a[++cnt]=j,num[j]++;
                    if(j!=0&&id==0)
                        id=cnt,flag1=1;
                 }
            }
            if(flag1==0){   //剩下的数全部为0
                for(int j=1;j<=cnt1;j++)
                    printf("%d",d[j]);
                for(int j=1;j<=cnt;j++)
                    printf("%d",a[j]);
            }
            else if(d[1]==0){
                printf("%d",a[id]);
                for(int j=1;j<id;j++)
                    printf("%d",a[j]);
                for(int j=1;j<=cnt1;j++)
                    printf("%d",d[j]);
                for(int j=id+1;j<=cnt;j++)
                    printf("%d",a[j]);
                printf("\n");
            }
            else{
                int cnt2=0,cnt3=0;
                NUM1[cnt2++]=a[id];
                for(int j=1;j<id;j++)
                    NUM1[cnt2++]=a[j];
                int flag2=0;
                for(int j=1;j<=cnt;j++){    //判断d一个出现不同与第一位的数是大于第一个还是小于
                    if(d[j]!=d[1]){     //以便确定插入的位置
                        if(d[j]<d[1])
                            flag2=1;
                        break;
                    }
                }
                for(int j=id+1;j<=cnt;j++){
                    if(a[j]==d[1]&&flag2==1){
                        for(int k=1;k<=cnt1;k++)
                            NUM1[cnt2++]=d[k];
                        flag2=-1;
                    }
                    else if(a[j]>d[1]&&flag2!=-1){
                        for(int k=1;k<=cnt1;k++)
                            NUM1[cnt2++]=d[k];
                        flag2=-1;
                    }
                    NUM1[cnt2++]=a[j];
                }
                if(flag2!=-1)
                    for(int k=1;k<=cnt1;k++)
                        NUM1[cnt2++]=d[k];
                for(int j=1;j<=cnt1;j++)
                    NUM2[cnt3++]=d[j];
                for(int j=1;j<=cnt;j++)
                    NUM2[cnt3++]=a[j];
                int j;
                for(j=0;j<=cnt2;j++){
                    if(NUM1[j]<NUM2[j]){
                        for(int j=0;j< cnt3;j++)
                            printf("%d",NUM1[j]);
                        break;
                    }
                    if(NUM1[j]>NUM2[j]){
                        for(int j=0;j<cnt3;j++)
                            printf("%d",NUM2[j]);
                        break;
                    }
                }
                if(j==cnt2+1)
                    for(int j=0;j<cnt3;j++)
                        printf("%d",NUM2[j]);
            }
            break;
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值