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

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5285762.html