https://codeforces.com/contest/1138/problem/D
题意:
有一种集训最佳安排,按照这个安排日程效果最佳。
现有一次集训,已经有了训练的日程。在只能调整顺序,不能修改总训练天数的情况下,尽量按照最佳训练日程进行。调整后后输出新的日程表。
实际就是给两个01串A和B,调整A的01顺序,让B尽可能多的作为字串在A中出现;解不唯一,输出一个符合要求的就可以。
思路:
让B尽量多出现A中,那么找到B的最大匹配前后缀p,将B分成p+q;
比如 101110101, p就是101,q就是110101
然后根据A中01的数量尽量去多的输出pqqqq... ,直到不够输出q后,把剩余的01输出完。
注意在找p的时候,暴力会T,可以用kmp算法中计算next数组的方法去算。
kmp算法:
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
// codeforce 1139-d
// KMP
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
int nex[500010];
int get_next(string q)
{
string p = q+'3';
int len = p.size();
nex[0] = -1;
int k = -1;
int j = 0;
while(j < len - 1)
{
if(k == -1 || p[j] == p[k])
nex[++j] = ++k;
else
k = nex[k];
}
/*
cout<<"-------------------------------------"<<endl;
cout<<p<<endl;
for(int i=0; i<=len; i++)
cout<<nex[i];
cout<<endl<<"-------------------------------------"<<endl;
*/
return nex[len-1];
}
int main()
{
string t;
string s;
cin>>s;
cin>>t;
int t_cnt = t.size();
string p;
int max_all = 0;
// 暴力求最大匹配前后缀
/*
for(int i=t_cnt-1; i>0; i--)
{
string a = t.substr(0,i);
string b = t.substr(t_cnt-i,i);
if(a==b)
{
max_all = i;
p = a;
break;
}
}
*/
// KMP找最大前后缀
max_all = get_next(t);
p = t.substr(0, max_all);
// printf("max_all = %d\n", max_all);
// cout<<"p = "<<p<<endl;
t = t.substr(max_all,t_cnt-max_all);
int s_cnt = s.size();
int p_cnt = p.size();
t_cnt = t.size();
int t_0 = 0;
int t_1 = 0;
for(int i=0; i<t_cnt; i++)
if (t[i] == '0')
t_0 ++;
t_1 = t_cnt-t_0;
int s_0 = 0;
int s_1 = 0;
for(int i=0; i<s_cnt; i++)
if (s[i] == '0')
s_0 ++;
s_1 = s_cnt-s_0;
int p_0 = 0;
int p_1 = 0;
for(int i=0; i<p_cnt; i++)
if (p[i] == '0')
p_0 ++;
p_1 = p_cnt-p_0;
/*
cout<<"begin to printf new char!\n";
cout<<"s_0 = "<<s_0<<"\ns_1 = "<<s_1<<endl;
cout<<"t_0 = "<<s_0<<"\nt_1 = "<<s_1<<endl;
cout<<"p_0 = "<<s_0<<"\np_1 = "<<s_1<<endl;
cout<<"s :"<<s<<endl;
cout<<"t :"<<t<<endl;
cout<<"p :"<<p<<endl;
*/
if(s_1 >= p_1 && s_0 >= p_0)
{
s_1 -= p_1;
s_0 -= p_0;
cout<<p;
}
while(s_1 >= t_1 && s_0 >= t_0)
{
s_1 -= t_1;
s_0 -= t_0;
cout<<t;
}
for(int i = 0; i<s_1; i++)
printf("1");
for(int i = 0; i<s_0; i++)
printf("0");
cout<<endl;
return 0;
}