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

浙公网安备 33010602011771号