Loading [MathJax]/extensions/tex2jax.js

「Codeforces 1138D」Camp Schedule 题解

解法

这道题其实就是考察 KMP 算法中 Next 数组的使用。题意转换过来大致就是:

给定两个 01 串,构造一个长度跟第一个串相同且 1 的个数相同的串,且保证第二个串的出现次数最多,出现可以重叠。

可以重叠的话,我们可以考虑贪心:后缀如果能跟前缀重合,那么出现的次数就有可能会变多。求出 Next 数组便是求出最长重合前后缀。我们可以循环添加字串的后缀,同时判断是否需要填充多余的 1 或 0。这样就搞定了。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}

Leave a Reply

Your email address will not be published. Required fields are marked *