题意:
给定 a , b a,b a,b和串 s s s, s s s只包含三种字符1
0
?
。问是否可以将 s s s中的?
转换成0
或1
,使得 s s s被构造成恰好有 a a a个0
和 b b b个1
的回文串。可以则输出构造的任意一种合法回文串,否则输出-1
数据范围: 0 ≤ a , b ≤ 2 × 1 0 5 , a + b ≥ 1 0\leq a,b\leq 2\times 10^5,a+b\geq 1 0≤a,b≤2×105,a+b≥1
题解:
先考虑所有已经可以确定的位置,即其位置或其回文位置已经有数字了,则可以直接放相应数字,否则根据 a , b a,b a,b的大小看可以放的字符。记得特判串为奇数的中间位置的情况。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
char s[N];
int a, b;
void solve() {
scanf("%d%d", &a, &b);
scanf("%s", s);
int n = strlen(s);
int f = 1, c = 0;
for(int i = 0; i < n >> 1; ++i) {
if(n % 2 && i == n - 1 - i) continue;
if(s[i] == '?' && s[n - 1 - i] == '?') continue;
if(s[i] == '?') {
int v = s[n - i - 1] - '0';
if(v == 0) a -= 2;
else b -= 2;
s[i] = v + '0';
}
else if(s[n - i - 1] == '?') {
int v = s[i] - '0';
if(v == 0) a -= 2;
else b -= 2;
s[n - i - 1] = v + '0';
}
else if(s[i] != s[n - i - 1]) f = 0;
else if(s[i] == '1') b -= 2;
else a -= 2;
}
for(int i = 0; i < n >> 1; ++i) {
if(n % 2 && i == n - 1 - i) continue;
if(s[i] == '?') {
if(a > 1) a -= 2, s[i] = s[n - i - 1] = '0';
else if(b > 1) b -= 2, s[i] = s[n - i - 1] = '1';
else f = 0;
}
}
if(n % 2) {
if(s[n >> 1] == '0') --a;
else if(s[n >> 1] == '1') --b;
else {
if(a >= 1) s[n >> 1] = '0', --a;
else if(b >= 1) s[n >> 1] = '1', --b;
else f = 0;
}
}
if(a != 0 || b != 0) f = 0;
if(f) puts(s);
else puts("-1");
}
int main()
{
int T = 1;
scanf("%d", &T);
for(int i = 1; i <= T; ++i) solve();
return 0;
}