题目
t(t<=1e4)组样例,每次给出n<=1e5,然后给出三个长度为2*n的01串
你需要构造出一个长度不超过3*n的串,使得该串的子序列中至少包含三个串中的两个串
显然一定有解,多解输出任一解,保证sumn<=1e5
思路来源
夏老师
题解
赛后感觉很sb,菜的div1要爆零了...
鸽巢原理,三个串中,必有两个串同时包含n个0或两个串同时包含n个1
假设第一个串过半的是0,第二个串过半的是1,则第三个显然放入其中一堆
即相当于在字符集只有01的情况下线性求出了lcs的感觉,考虑求出了lcs怎么构造答案
两个串当前扫到的字符分别是i,j,当前超过n次出现的数字是0
如果i字符不是0,直接放入直到i是0;
如果j字符不是0同理,然后i、j共同往前迈0的一步
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n,cnt[3][2];
char s[3][N*2],ans[N*3];
void con(char *s,char *t,char x){
int c=0;
for(int i=0,j=0;i<2*n || j<2*n;i++,j++){
while(i<2*n && s[i]!=x)ans[c++]=s[i++];
while(j<2*n && t[j]!=x)ans[c++]=t[j++];
if(i>=2*n && j>=2*n)break;
ans[c++]=x;
}
ans[c++]='\0';
printf("%s\n",ans);
}
void solve(){
for(int i=0;i<3;++i){
for(int j=i+1;j<3;++j){
for(int k=0;k<2;++k){
if(cnt[i][k]>=n && cnt[j][k]>=n){
con(s[i],s[j],k+'0');
return;
}
}
}
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(cnt,0,sizeof cnt);
for(int i=0;i<3;++i){
scanf("%s",s[i]);
for(int j=0;j<2*n;++j){
cnt[i][s[i][j]-'0']++;
}
}
solve();
}
return 0;
}