codeforces 180D

题意:给你两个字符串s、t,输出由s组成的字符的一个排列,使得s字典序大于t,且字典序尽可能小

做法,贪心,要使字典序尽可能小又要大于t的字典序,则应该使得答案串与t串的前缀尽可能多的相同

然后就分两步走了

1 如果s中包含了t中的所有字符,且有多余的字符(因为字典序要严格大于t),则直接输出t,在接在后面输出剩下的字符的最小字典序的一个排列

2 假如1的条件不成立,就找这样一个位置,这个位置之前的字符都可以做到和t相同,且这个位置的字符要比t相应位置大,

因为要是前缀尽可能多的相同,所以贪心的从后往前求这个位置,找到这个位置后就可以把s中剩下的字符一并输出了

View Code
#include<cstdio>
#include<cstring>
const int maxn = 5010;
char s[maxn];
char t[maxn];
int a[30],b[30];
int main()
{
    int i,j,k,l;
    bool can,flag;
    while(scanf("%s%s",s,t)!=EOF)
    {
        can=true;
        int lens=strlen(s);
        int lent=strlen(t);
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(i=0;i<lens;i++) a[s[i]-'a']++;
        for(i=0;i<lent;i++) b[t[i]-'a']++;
        int more=0;
        for(i=0;i<26;i++) 
        {
            if(a[i]<b[i]) can=false;
            if(a[i]>b[i]) more++;
        }
        int cnt;
        if(can&&more){
            cnt=lent;
            for(i=0;i<26;i++)for(j=0;j<a[i]-b[i];j++)
            t[cnt++]='a'+i;
            t[cnt]='\0';
            printf("%s\n",t);
            continue;
        }
        flag=false;
        for(i=lent-1;i>=0;i--)
        {
            can=true;
            b[t[i]-'a']--;
            for(j=0;j<26;j++) if(a[j]<b[j]) can=false;
            if(!can) continue;
            for(j=0;j<26;j++) if(j>t[i]-'a' && a[j]>b[j])
            {
                flag=true;
                a[j]--;
                t[i]='a'+j;
                cnt=i+1;
                for(i=0;i<26;i++) for(j=0;j<a[i]-b[i];j++)
                t[cnt++]='a'+i;
                t[cnt]=0;
                printf("%s\n",t);
                break;
            }
            if(flag)  break;
        }
        if(!flag) printf("-1\n");
    }
    return 0;
}
posted @ 2012-04-22 20:24  Because Of You  Views(351)  Comments(0Edit  收藏  举报