Problem - 1137B - Codeforces
在全国范围内广为人知的春季编程训练营即将开始。因此,所有友好的策展人和教师团队开始组成营地的时间表。经过不断的讨论,他们想出了一个时间表,可以表示为一个二进制字符串,其中第i个符号是 "1",如果学生将在第i天写比赛,"0",如果他们将有一天休息。
在最后时刻,Gleb说,如果夏令营按照时间表t(可以用与时间表s相同的格式来描述)运行,那么它将是最有成效的。由于当前的天数可能与时间表t中的天数不同,Gleb要求营地的时间表必须被改变,使t在其中作为子串出现的次数达到最大可能。同时,比赛日和休息日的数量不应改变,只是它们的顺序可以改变。
你能以最佳方式重新安排时间表吗?
输入
第一行包含字符串s (1⩽|s|⩽500000),表示营地日程表的当前项目。
第二行包含字符串t (1⩽|t|⩽500000),表示Gleb认为的最佳时间表。
字符串s和t只包含字符'0'和'1'。
输出
打印的计划表应该只包含字符'0'和'1',零的数量应该等于s中零的数量,一的数量应该等于s中一的数量。
如果有多个最佳时间表,则打印其中任何一个。
例子
inputCopy
101101
110
outputCopy
110110
输入副本
10010110
100011
输出拷贝
01100011
输入副本
10
11100
输出拷贝
01
注意
在第一个例子中,有两个出现,一个从第一位置开始,一个从第四位置开始。
在第二个例子中,只有一个从第三位开始的出现。注意,答案不是唯一的。例如,如果我们把第一天(即休息日)移到最后一个位置,t的出现次数不会改变。
在第三个例子中,甚至不可能出现一个。
题解:
贪心是写不了这道题的
假如子串是101这种
应该10101这样构造
我们每次应该找到其最大后缀与前缀相等的字符串的长度,其实就是ne数组
我们构建一个t串的ne数组,寻找一下最大前缀和后缀所匹配的地方,然后在这个地方后面的一个单位继续构造即可,因为都匹配了,所以上一个构造好的子串的后缀,就可以充当下一个需要构造的子串的前缀,这样构造的话,最后答案一定是最优解
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<stack>
#include<set>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int N = 1e6 + 10;
char a[N],b[N],ans[N];
int cnt[N];
int ne[N];
void solve()
{
cin >> a >> b;
int n = strlen(a);
int m = strlen(b);
for(int i = 0; i< n;i++)
{
cnt[a[i] - '0']++;
}
ne[0] = -1;
int i = 0,j = -1;
while(i < m)
{
if(j == -1||b[j] == b[i])
{
ne[++i] = ++j;
}
else
j = ne[j];
}
for(int i = 0,j = 0;i < n;i++,j++)
{
if(j == m)
j = ne[j];
if(cnt[b[j] - '0'])
{
ans[i] = b[j];
cnt[b[j] - '0']--;
}
else
{
ans[i] = '0' + ((b[j] - '0')^1);
cnt[(b[j]-'0')^1]--;
}
}
cout << ans;
}
//1 -7 1 -7
signed main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}
//3 3 2 2 1 0
//1 2 1 1 1 0