链接:
https://codeforces.ml/gym/102823/problem/H
题意:
HM(a,b)表示字符串a和b的汉明距离,定义两个字符串不同点的数量
给两个字符串a,b,求构建一个满足HM(a,c)=HM(b,c)的最小字典序C
解:
2018CCPC的桂林H题
前段时间摸了一下虚拟赛,确确实实是蒟蒻了
当时是和思路找a和b中字符’a’的数量,然后根据数量差,前面全填’a’,从后面开始修改对应数量差的字符(然后卡死了,处理没写出来)
这边补一下这题=-=
如果ai和bi是相同的话,那么无论ci是什么字符,他们的汉明值[HM(a,c)和HM(b,c)]都不会变
如果ci不和ai、bi相同的话他们的汉明值也不会变
但是,如过ai和bi在这个位置不相同,且我们让ci和其中一个相同,就能影响一点汉明值
那么,我们以后缀和的方式标记两个串每个后置后面的不同的位置的数量(为什么呢)
为了字典序最小,我们从最前面开始填充,直接遍历’a’到’z’(实际上,只要判断4个字符,‘a’,ai,bi和除了ai,bi离’a’最近的字符)
设置一开始的汉明差[HM(a,c)-HM(b,c)]为0,那么如果我们填充字符和a不同,汉明差就加一,和b不同,汉明差再减一
那么在这个点上的前缀汉明差,要大于等于后后缀的不同的位置的数量,这样就能保住我填入这个字符,而后面是有办法使之合法
即通过等于ai或者ci来调整汉明差(字典序最小所以优先前面填小的)
那么为什么不能拿汉明差和整段的不同的位置的数量进行比较呢,因为如果对于这个位置上的不同字符,我填与之都不相同的字符,那么这个位置及前面的汉明差是不变的,但是这个位置已经填完了,失去了调整汉明差的作用!
实际代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#define csh(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long int ll;
const int Size=1E6+5;
int sz[Size];
string a,b;
char tc(int change,int i)
{
for(char ch='a';ch<='z';ch++)
{
int tempHM=change;
if(ch!=a[i]) tempHM++;//填充这个字母和a串对于字母不同,HM(a)增加
if(ch!=b[i]) tempHM--;//填充这个字母和b串对于字母不同,HM(b)增加
if(abs(tempHM) <= sz[i+1])//可以修正
{
return ch;
}
}
}
int main()
{
int T;
cin>>T;
for(int f=1;f<=T;f++)
{
cin>>a>>b;
int lg=a.length();
sz[lg]=0;
for(int i=lg-1;i>=0;i--)
{
sz[i]=sz[i+1];
if(a[i]!=b[i]) sz[i]++;//后缀不相等量
//如果相同,那么那个位置上不论放置什么字符 HM(a)和HM(b)都不会受到影响
//那么,每一个不同之处,都能让修正前面的HM差
}
int change=0;//目前情况下对于a,b的HM差,定为HM(a)-HM(b);
cout<<"Case "<<f<<": ";//案例标记
for(int i=0;i<lg;i++)
{
char c=tc(change,i);
cout<<c;
if(c!=a[i]) change++;//修改前面的HM差标记
if(c!=b[i]) change--;
}
cout<<endl;
}
}
限制:
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output