前言
练习赛的时候降智写了一车面包锅,赛后一写就过。
题目
题目大意:
给定一个正整数 (n),接着输入三个长度为 (2n) 的01字符串,要求构造一个长度不超过 (3n) 的字符串使得至少给定的两个串为你构造的串的子序列。
多组数据,(sum nle 10^5)。
讲解
其实这道题还是比较好想的。
我们发现如果其中两个串的最长公共子序列能够达到 (n),那么我们将剩下的都按对应的位置插入进去,就可以构造出合法解。
根据鸽巢原理可知一个长度为 (2n) 的01字符串,一定会使得0或1达到半数。
而题目给了三个串,那么一定会有两个串使得0或1都达到半数,随便写写就好。
注意数组不要开小了。
代码
又丑又长。
bool check(int x,int y)
{
int cnt1 = 0,cnt2 = 0;
for(int i = 1;i <= 2*n;++ i)
{
if(a[x][i] == '0') cnt1++;
if(a[y][i] == '0') cnt2++;
}
if(cnt1 >= n && cnt2 >= n)
{
int MIN = Min(cnt1,cnt2),now1 = 1,now2 = 1;
for(int i = 1;i <= MIN;++ i)
{
while(a[x][now1] != '0') putchar(a[x][now1]),now1++;
while(a[y][now2] != '0') putchar(a[y][now2]),now2++;
putchar('0');
now1++;
now2++;
}
for(int i = now1;i <= 2*n;++ i) putchar(a[x][i]);
for(int i = now2;i <= 2*n;++ i) putchar(a[y][i]);
putchar('
');
return 1;
}
cnt1 = 2*n - cnt1; cnt2 = 2*n - cnt2;//1的个数
if(cnt1 >= n && cnt2 >= n)
{
int MIN = Min(cnt1,cnt2),now1 = 1,now2 = 1;;
for(int i = 1;i <= MIN;++ i)
{
while(a[x][now1] != '1') putchar(a[x][now1]),now1++;
while(a[y][now2] != '1') putchar(a[y][now2]),now2++;
putchar('1');
now1++;
now2++;
}
for(int i = now1;i <= 2*n;++ i) putchar(a[x][i]);
for(int i = now2;i <= 2*n;++ i) putchar(a[y][i]);
putchar('
');
return 1;
}
return 0;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
for(int T = Read(); T ;-- T)
{
n = Read();
for(int i = 0;i < 3;++ i) scanf("%s",a[i]+1);
bool f = 1;
for(int i = 0;i < 3 && f;++ i)//其实不需要这么多次
for(int j = 0;j < 3 && f;++ j)
if(i != j && check(i,j))
f = 0;
}
return 0;
}