最近已经很久没有弄csdn和刷题了,感觉自己水了不少,还是要赶紧刷题准备比赛才行啊。
题目介绍
Professor GukiZ doesn’t accept string as they are. He likes to swap some letters in string to obtain a new one.
GukiZ has strings a, b, and c. He wants to obtain string k by swapping some letters in a, so that k should contain as many non-overlapping substrings equal either to b or c as possible. Substring of string x is a string formed by consecutive segment of characters from x. Two substrings of string x overlap if there is position i in string x occupied by both of them.
GukiZ was disappointed because none of his students managed to solve the problem. Can you help them and find one of possible strings k?
Input
The first line contains string a, the second line contains string b, and the third line contains string c (1 ≤ |a|, |b|, |c| ≤
105
, where |s| denotes the length of string s).
All three strings consist only of lowercase English letters.
It is possible that b and c coincide.
Output
Find one of possible strings k, as described in the problem statement. If there are multiple possible answers, print any of them.
题目说的是我们要重新组合string a,每次可以swap a 的任意两个字符,使输出的string满足不重叠连续字串能和 b/c 匹配的次数最多。
算法
读完题之后就觉得有点那种线性规划的意思,就是那种b,c两个字符串的线性组合。然后因为对 a 的交换任意两个字符的这个操作可以得到 a 中字符的任意排列,所以我们也就不在乎最终得到的字符串是否合法,只要和 a 具有相同的字母统计即可了。
比赛的时候贪心了一发,先算出两个数res1和res2分别代表如果只匹配b和只匹配c能够有多少个, 然后挑选最大的那个数字(比如说是res1),先输出res1个b,然后再做一次统计看还有多少个c可以被输出。之后输出够c之后,再把剩余的字符串都输出出来。这种方法一直被卡在test12,知道比赛结束也没有AC。
之后看到了别人的评论,说明贪心其实是不可以的。举个例子来说
aacaacbbaac
aac
ab
这组数据,如果用贪心法的话会是3,但是最优解却是4,估计是我比赛的时候脑子有些不灵光,想了一个错误的证明并且走了错误的道路。
所以最后的解决方案就是枚举所有可行解,t1个b,t2个c,取t1+t2最大的时候的匹配模式输出。但是这里还是要进行一发提前检测的,同上,看res1和res2哪个大,就从哪个开始枚举,否则当 res1=0 且 res2!=0 的时候就会跪。
代码
#include "stdafx.h"
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <memory.h>
#include <cassert>
#include <string>
#include <queue>
using namespace std;
int n, m, p, q, t, r;
long long res;
string s1, s2, s3;
int a[30]; // a的统计数据
int b[30]; // b的统计数据
int c[30]; // c的统计数据
int aa[30]; // 这个是为了输出时候的方便,用aa代替a被修改
int main() {
cin >> s1 >> s2 >> s3; // 输入的a,b,c字符串
for (int i = 0; i < s1.length(); i++) {
a[s1[i] - 'a']++;
aa[s1[i] - 'a']++;
}
for (int i = 0; i < s2.length(); i++) {
b[s2[i] - 'a']++;
}
for (int i = 0; i < s3.length(); i++) {
c[s3[i] - 'a']++;
}
// 检验如果只输出b能有多少个
int temp = 10000000;
for (int i = 0; i <= 25; i++) {
if (b[i] == 0) continue;
temp = min(a[i] / b[i],temp);
}
// 检验如果只输出c能有多少个
int temp2 = 10000000;
for (int i = 0; i <= 25; i++) {
if (c[i] == 0) continue;
temp2 = min(a[i] / c[i], temp2);
}
int sum = 0;
int res1 = 0; int res2 = 0;
if (temp > temp2) {
for (int i = 1; i <= temp; i++) {
// 枚举输出b的个数
for (int t = 0; t <= 25; t++) {
aa[t] = a[t];
}
for (int kk = 0; kk < s2.length(); kk++) {
aa[s2[kk] - 'a'] -= i;
}
// 在此输出b的数量下,还有多少个c能被输出
int temp2 = 10000000;
for (int i = 0; i <= 25; i++) {
if (c[i] == 0) continue;
temp2 = min(aa[i] / c[i], temp2);
}
if (temp2 + i > sum) {
sum = temp2 + i;
res1 = i; res2 = temp2;
}
}
}
else {
for (int i = 1; i <= temp2; i++) {
// 输出C的个数
for (int t = 0; t <= 25; t++) {
aa[t] = a[t];
}
for (int kk = 0; kk < s3.length(); kk++) {
aa[s3[kk] - 'a'] -= i;
}
// 在此输出C的数量下,还有多少个B能被输出
int temp = 10000000;
for (int i = 0; i <= 25; i++) {
if (b[i] == 0) continue;
temp = min(aa[i] / b[i], temp);
}
if (temp + i > sum) {
sum = temp + i;
res2 = i; res1 = temp;
}
}
}
for (int i = 1; i <= res1; i++) {
cout << s2;
}
for (int i = 0; i < s2.length(); i++) {
a[s2[i] - 'a'] -= res1;
}
for (int i = 1; i <= res2; i++) {
cout << s3;
}
for (int i = 0; i < s3.length(); i++) {
a[s3[i] - 'a'] -= res2;
}
for (int i = 0; i <= 25; i++) {
for (int j = 0; j < a[i]; j++) {
cout << (char)(i + 'a');
}
}
return 0;
}
照例自我介绍:
ID: Oh2
github: http://github.com/oh233
csdn: http://blog.csdn.net/oh233
个人网站: http://oh233.com
知乎: http://www.zhihu.com/people/qi-hao-zhi-65