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