Codeforces Round #155 (Div. 2) C YY题目
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; }