http://codeforces.com/problemset/problem/254/C
题意:
定义t是s的Anagram,满足条件是:t与s的字符相同。strings "DOG" and "GOD" are anagrams
给定两个串,分别为s,t 求满足s经过最少的替换次数能够成为t的Anagram的可能里面的字典序最小的字符串。输出最少次数和经过替换后的最小字典序的s
思路:
总共一共26个英文字母,我们记录每一个英文字母需要加减的个数(即要替换的和被替换的个数)。然后遍历一遍s,当前字符如果需要减小,则用需要增加字符里面最小得的替换。这里关键是如何替换:
(我这里减少的字符表示要替换的字符,增加的字符表示要用来替换的字符)
替换规则:
如果该字符是减少的字符:
如果要减少的字符比要增加的最小的字符大,则用要增加的最小的字符替换;否则检查当前要减小的字符是否必须用要增加的字符替换。如果是则替换,否则让给后边需要替换。
否则:不变
这样就保证了,如果该字符需要替换则用的肯定是最小的字符替换了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x) ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)
#define ll long long
#define inf 0x7f7f7f7f
#define MOD 1073741824
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 150
#define N 100007
using namespace std;
//freopen("din.txt","r",stdin);
/*
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
*/
int num1[30],num2[30];
int jin[30],jia[30];
string s1,s2;
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
//int T,cas = 1;
int i,j;
cin>>s1>>s2;
int len = s1.size();
CL(num1,0); CL(num2,0);
CL(jin,0); CL(jia,0);
//记录字符个数
for (i = 0; i < len; ++i)
{
num1[s1[i] - 'A']++;
num2[s2[i] - 'A']++;
}
int ans = 0;
for (i = 0; i < 26; ++i)
{
ans += iabs(num1[i] - num2[i]);//总的需要替换的个数
jia[i] = num2[i] - num1[i];//要加的字符的个数
jin[i] = num1[i] - num2[i];//要减的字符的个数
if (jia[i] < 0) jia[i] = 0;
if (jin[i] < 0) jin[i] = 0;
}
for (i = 0; i < len; ++i)
{
int p = s1[i] - 'A';
// printf("%c %d\n",s1[i],jin[p]);
if (jin[p])//如果该字符要减
{
for (j = 0; j < 26; ++j)
{
if (jia[j])//找到最小的可用来替换的字符
{
if (j < p)//如果比它小则替换
{
s1[i] = j + 'A';
jia[j]--;
jin[p]--;
num1[p]--;
}
else
{
//printf(">>>%d %d %d\n",p,jin[p],num1[p]);
if (jin[p] >= num1[p])//剩下的字母p必须都替换
{
s1[i] = j + 'A';
jia[j]--;
jin[p]--;
num1[p]--;
}
else num1[p]--;//剩下的不必都替换,这样保证了不替换的p<j 保证了字典序最小
}
break;
}
}
}
else num1[p]--;//现在的num1记录的是从当前点到结束点该字符的个数
}
printf("%d\n",ans/2);
cout<<s1<<endl;
return 0;
}