CF1085E Vasya and Templates

字典序,构造,暴力

题意

给定字符串 \(s\)\(a\)\(b\),以及其字符集 \(k\)(表示其由前 \(k\) 个字母组成)。

构造一组映射关系,使得将其应用于 \(s\) 后得到的字符串,字典序不小于字符串 \(a\),且不大于字符串 \(b\)

\(1 \le |s| \le 10^6\)

题解

容易发现,如果对于一个位置 \(i\),使得新的 \(s_i \in (a_i,b_i)\),那么直接结束战斗了(后面的可以随便选)。

因此每一个位置只有两种情况:选 \(a_i\) 或 选 \(b_i\)(选到中间的一定满足条件),据此暴力即可。

但发现代码需要大量分支语句,于是求助题解,发现可以直接暴力枚举每个字母的映射关系,再稍加优化即可,具体见代码,复杂度正确性就是上述性质。

代码

#include<bits/stdc++.h>
// #define int long long
using namespace std;
const int Maxn=1e6+10;
char s[Maxn],a[Maxn],b[Maxn];
int n,k;
map<char,char>mp;
int vis[200];
bool dfs(int p,bool up,bool dn)
{
    // cout<<p<<" "<<up<<" "<<dn<<" "<<s[p]<<endl;
    if(p==n+1) return 1;
    if(mp[s[p]])
    {
        if((up&&a[p]>mp[s[p]]) || (dn&&b[p]<mp[s[p]]) || !dfs(p+1,up&&(mp[s[p]]==a[p]),dn&&(mp[s[p]]==b[p]))) return 0;
        return 1;
    }
    char st=(up?a[p]:'a'),ed=(dn?b[p]:'a'+k-1);
    for(char i=st;i<=ed;i++)
    {
        if(vis[i]) continue;
        vis[i]=1; mp[s[p]]=i;
        if(dfs(p+1,up&&i==a[p],dn&&i==b[p])) return 1;
        vis[i]=0; mp[s[p]]=0;
    }
    return 0;
}
void run()
{
    memset(vis,0,sizeof(vis));
    mp.clear();
    cin>>k;
    cin>>(s+1)>>(a+1)>>(b+1);
    n=strlen(s+1);
    if(dfs(1,1,1))
    {
        char c='a';
        cout<<"YES"<<endl;
        for(char i='a';i<='a'+k-1;i++)
        {
            if(mp[i]) cout<<mp[i];
            else 
            {
                while(c<='a'+k-1 && vis[c]) c++;
                cout<<c; vis[c]=1;
            }
        }
        cout<<endl;
    }
    else cout<<"NO"<<endl;
}
signed main()
{
    int T;
    cin>>T;
    while(T--) run();
    return 0;
}
posted @ 2025-12-15 19:06  crazy--boy  阅读(4)  评论(0)    收藏  举报