CoderForce 180D-Name (构造+回溯)
题目大意:给两个字符串s,t,用s中的字符重新组合构造出按字典序最小的但比t大的新字符串。
题目分析:先统计s中各个字母出现的次数,然后从t的左端向右端依次构造出新串的每一位上的字母。这个过程我是用回溯实现的,因为只需进行到字典序比t大就可以立即停止,所以实际上花不了多少时间。
代码如下:
# include<iostream> # include<string> # include<algorithm> # include<cstdio> # include<vector> # include<cstring> using namespace std; int n,m; int vis[5005]; string p,q; int cnt[26]; int ans[5005]; int isBigger() { for(int i=1;i<=ans[0]&&i-1<m;++i){ if(ans[i]<q[i-1]-'a') return -1; if(ans[i]>q[i-1]-'a') return 1; } if(ans[0]==m) return 0; else if(ans[0]>m) return 1; else return -1; } bool dfs(int i) { int k=isBigger(); if(k>0) return true; if(i>=m){ if(k>0) return true; else if(k==0) return n>m; else if(k<0) return false; } for(char c=q[i];c<='z';++c){ if(cnt[c-'a']==0) continue; --cnt[c-'a']; ans[++ans[0]]=c-'a'; if(dfs(i+1)) return true; --ans[0]; ++cnt[c-'a']; } return false; } int main() { //while(cin>>p>>q){ cin>>p>>q; n=p.size(); m=q.size(); memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;++i) ++cnt[p[i]-'a']; ans[0]=0; if(!dfs(0)) printf("-1\n"); else{ for(int i=1;i<=ans[0];++i) cout<<(char)(ans[i]+'a'); for(int i=0;i<26;++i) for(int j=0;j<cnt[i];++j) cout<<(char)(i+'a'); cout<<endl; } //} return 0; }