解法
这道题其实就是考察 KMP 算法中 Next 数组的使用。题意转换过来大致就是:
给定两个 01 串,构造一个长度跟第一个串相同且 1 的个数相同的串,且保证第二个串的出现次数最多,出现可以重叠。
可以重叠的话,我们可以考虑贪心:后缀如果能跟前缀重合,那么出现的次数就有可能会变多。求出 Next 数组便是求出最长重合前后缀。我们可以循环添加字串的后缀,同时判断是否需要填充多余的 1 或 0。这样就搞定了。
代码
// D.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 501000;
string A, B;
int totA, totB, nxt[MAX_N];
void getNext(string str)
{
string tmp = " " + str;
for (int i = 2; i <= tmp.length() - 1; i++)
{
int j = nxt[i - 1];
while (j && tmp[j + 1] != tmp[i])
j = nxt[j];
if (tmp[j + 1] == tmp[i])
nxt[i] = j + 1;
else
nxt[i] = 0;
}
}
int main()
{
cin >> A >> B;
getNext(B);
for (int i = 0; i < A.length(); i++)
totA += A[i] - '0';
for (int i = 0; i < B.length(); i++)
totB += B[i] - '0';
if (A.length() < B.length() || totA < totB)
cout << A, exit(0);
A = " " + A, B = " " + B;
int ans = A.length();
for (int i = 1, j = 0; i < A.length(); i++)
{
if (totA && B[j + 1] == '1')
totA--, A[i] = '1', j++;
else if (B[j + 1] == '0')
A[i] = '0', j++;
else
{
ans = i;
break;
}
if (j == B.length() - 1)
j = nxt[j];
}
for (int i = ans; i < A.length(); i++)
A[i] = '0';
while (totA)
{
ans--;
if (A[ans] == '1')
totA++;
A[ans] = '1', totA--;
}
cout << A.substr(1);
return 0;
}
// D.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 501000;
string A, B;
int totA, totB, nxt[MAX_N];
void getNext(string str)
{
string tmp = " " + str;
for (int i = 2; i <= tmp.length() - 1; i++)
{
int j = nxt[i - 1];
while (j && tmp[j + 1] != tmp[i])
j = nxt[j];
if (tmp[j + 1] == tmp[i])
nxt[i] = j + 1;
else
nxt[i] = 0;
}
}
int main()
{
cin >> A >> B;
getNext(B);
for (int i = 0; i < A.length(); i++)
totA += A[i] - '0';
for (int i = 0; i < B.length(); i++)
totB += B[i] - '0';
if (A.length() < B.length() || totA < totB)
cout << A, exit(0);
A = " " + A, B = " " + B;
int ans = A.length();
for (int i = 1, j = 0; i < A.length(); i++)
{
if (totA && B[j + 1] == '1')
totA--, A[i] = '1', j++;
else if (B[j + 1] == '0')
A[i] = '0', j++;
else
{
ans = i;
break;
}
if (j == B.length() - 1)
j = nxt[j];
}
for (int i = ans; i < A.length(); i++)
A[i] = '0';
while (totA)
{
ans--;
if (A[ans] == '1')
totA++;
A[ans] = '1', totA--;
}
cout << A.substr(1);
return 0;
}
// D.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 501000; string A, B; int totA, totB, nxt[MAX_N]; void getNext(string str) { string tmp = " " + str; for (int i = 2; i <= tmp.length() - 1; i++) { int j = nxt[i - 1]; while (j && tmp[j + 1] != tmp[i]) j = nxt[j]; if (tmp[j + 1] == tmp[i]) nxt[i] = j + 1; else nxt[i] = 0; } } int main() { cin >> A >> B; getNext(B); for (int i = 0; i < A.length(); i++) totA += A[i] - '0'; for (int i = 0; i < B.length(); i++) totB += B[i] - '0'; if (A.length() < B.length() || totA < totB) cout << A, exit(0); A = " " + A, B = " " + B; int ans = A.length(); for (int i = 1, j = 0; i < A.length(); i++) { if (totA && B[j + 1] == '1') totA--, A[i] = '1', j++; else if (B[j + 1] == '0') A[i] = '0', j++; else { ans = i; break; } if (j == B.length() - 1) j = nxt[j]; } for (int i = ans; i < A.length(); i++) A[i] = '0'; while (totA) { ans--; if (A[ans] == '1') totA++; A[ans] = '1', totA--; } cout << A.substr(1); return 0; }