题目链接:
题意:
给定一个01串s,再给定一个字符串t,现在可以随意交换s中元素顺序,使得交换后的串中含t的数目最多(t作为子串)。输出交换后的串,special judge。
思路:
贪心思路,求 t 的后缀与前缀匹配的最大长度。固定重合部分,然后重复剩余部分即可。
如何求 t 的后缀与前缀匹配的最大长度?
一、求kmp的Next数组
二、字符串哈希。注意:模数不要用unsigned long long的自然溢出,会疯狂wa第71个样例.....用双模数字符串哈希就能过。(单模数没试过,应该也能过,自然溢出真的辣鸡.....)
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> PLL;
const int MAX = 500000 + 100;
const ll mod1 = 998244353;
const ll mod2 = 1e9 + 7;
const ull p = 233;
string s, t;
string ans;
PLL bin[MAX];
PLL Hash[MAX];
string tmp;
void init() {
bin[0].first = 1;
bin[0].second = 1;
for (int i = 1; i <= 500000 + 10; i++) {
bin[i].first = bin[i - 1].first * p%mod1;
bin[i].second = bin[i - 1].second * p%mod2;
}
}
inline ll getsub1(int l, int r) {
return (Hash[r].first - Hash[l - 1].first * bin[r - l + 1].first%mod1 + mod1) % mod1;
}
inline ll getsub2(int l, int r) {
return (Hash[r].second - Hash[l - 1].second * bin[r - l + 1].second % mod2 + mod2) % mod2;
}
int main()
{
ios::sync_with_stdio(false);
init();
cin >> s >> t;
int len1 = s.length();
int len2 = t.length();
int num0 = 0, num1 = 0;
for (int i = 0; i < len1; i++) {
if (s[i] == '0') num0++;
else num1++;
}
Hash[0].first = 0;
Hash[1].second = 0;
for (int i = 1; i <= len2; i++) {
Hash[i].first = (Hash[i - 1].first * p%mod1 + (t[i - 1] - '0' + 1))%mod1;
Hash[i].second = (Hash[i - 1].second * p%mod2 + (t[i - 1] - '0' + 1)) % mod2;
}
int pos = -1;
for (int i = 1; i < len2; i++) {
if ((getsub1(i + 1, len2) == getsub1(1, len2 - i)) && (getsub2(i + 1, len2) == getsub2(1, len2 - i))) {
pos = i;
break;
}
}
int need0 = 0, need1 = 0;
if (pos == -1) {
for (int i = 0; i < len2; i++) {
if (t[i] == '0') need0++;
else need1++;
}
tmp = t;
}
else {
for (int i = len2 - pos; i < len2; i++) {
if (t[i] == '0') need0++;
else need1++;
tmp += t[i];
}
for (int i = 0; i <= len2 - pos - 1; i++) {
if (t[i] == '0') num0--;
else num1--;
ans += t[i];
}
}
if (num0 < 0 || num1 < 0) {
cout << s << endl;
return 0;
}
while (true) {
if ((num0 >= need0) && (num1 >= need1)) {
ans += tmp;
num0 -= need0;
num1 -= need1;
}
else {
for (int i = 0; i < num0; i++)
ans += '0';
for (int i = 0; i < num1; i++)
ans += '1';
break;
}
}
cout << ans << endl;
return 0;
}