构造 - Binary String Reconstruction - CF 1400C
Consider the following process. You have a binary string (a string where each character is either 0 or 1) w of length n and an integer x. You build a new binary string s consisting of n characters. The i-th character of s is chosen as follows:
if the character
w
i
−
x
w_{i−x}
wi−x exists and is equal to 1, then si is 1 (formally, if
i
>
x
i>x
i>x and
w
i
−
x
=
1
w_{i−x}= 1
wi−x=1, then
s
i
=
1
s_i= 1
si=1);
if the character
w
i
+
x
w_{i+x}
wi+x exists and is equal to 1, then si is 1 (formally, if
i
+
x
≤
n
i+x≤n
i+x≤n and
w
i
+
x
=
1
w_{i+x}= 1
wi+x=1, then
s
i
=
1
s_i= 1
si=1);
if both of the aforementioned conditions are false, then si is 0.
You are given the integer x and the resulting string s. Reconstruct the original string w.
Input
The first line contains one integer t (
1
≤
t
≤
1000
1≤t≤1000
1≤t≤1000) — the number of test cases.
Each test case consists of two lines. The first line contains the resulting string s ( 2 ≤ ∣ s ∣ ≤ 1 0 5 2≤|s|≤10^5 2≤∣s∣≤105, each character of s is either 0 or 1). The second line contains one integer x ( 1 ≤ x ≤ ∣ s ∣ − 1 1≤x≤|s|−1 1≤x≤∣s∣−1).
The total length of all strings s in the input does not exceed 105.
Output
For each test case, print the answer on a separate line as follows:
if no string w can produce the string s at the end of the process, print −1;
otherwise, print the binary string w consisting of |s| characters. If there are multiple answers, print any of them.
Example
input
3
101110
2
01
1
110
1
output
111011
10
-1
分析:
- 对于
s
[
i
]
=
′
1
′
s[i]='1'
s[i]=′1′,可能有两种情况:
- i > x i>x i>x && w [ i − x ] = ′ 1 ′ w[i-x]='1' w[i−x]=′1′
- i + x ≤ n i+x\le n i+x≤n && w [ i + x ] = ′ 1 ′ w[i+x]='1' w[i+x]=′1′
- 对于 s [ i ] = ′ 0 ′ s[i]='0' s[i]=′0′,则: w [ i − x ] = ′ 0 ′ w[i-x]='0' w[i−x]=′0′ && w [ i + x ] = ′ 0 ′ w[i+x]='0' w[i+x]=′0′
①、首先,我们可以根据
s
[
i
]
=
′
0
′
s[i]='0'
s[i]=′0′ 确定 w 中哪些位置一定要放 0
,其他位置均放置 1
即可。
\qquad
因为,当我们处理完 s 中的 0
后,对于剩下的 1
,只要两侧存在一个 1
即可满足条件,
\qquad
我们为了方便起见,不考虑在哪一侧放 1
,直接在非 0
的位置放 1
。
②、然后,我们考虑
s
[
i
]
=
′
1
′
s[i]='1'
s[i]=′1′,来检测错误。此时,失败的条件就显然了,当我们放 1
的时候,如果对于某个
s
[
i
]
=
′
1
′
s[i]='1'
s[i]=′1′,我们无法通过在左侧或右侧放置 1
时,我们就认为失败了。
③、最后,不要忘了把空着的字符都填充上 1
,因为当步长较大时,会有区间更新不到。如上图,绿色的区域是我们会更新到的区域,中间的红色区域
[
n
−
x
+
1
,
1
+
x
−
1
]
[n-x+1,1+x-1]
[n−x+1,1+x−1] 是我们更新不到的区域。也就是当
n
+
1
≤
2
x
n+1\le 2x
n+1≤2x 时就会出现更新不到的区域。
注意: 多测清空答案数组时,要清空到字符串长度的后一位。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100010;
int T, x;
char s[N], ans[N];
bool solve()
{
int n = strlen(s + 1);
for(int i = 0; i <= n + 1; i ++) ans[i] = '\0';
for(int i = 1; i <= n; i ++)
if(s[i] == '0')
{
if(i > x) ans[i - x] = '0';
if(i + x <= n) ans[i + x] = '0';
}
for(int i = 1; i <= n; i ++)
if(s[i] == '1')
{
bool flag = false;
if(i > x && ans[i - x] != '0')
{
ans[i - x] = '1';
flag = true;
}
if(i + x <= n && ans[i + x] != '0')
{
ans[i + x] = '1';
flag = true;
}
if(!flag) return false;
}
for(int i = 1; i <= n; i ++) if(ans[i] == '\0') ans[i] = '1';
return true;
}
int main()
{
scanf("%d", &T);
while(T --)
{
scanf("%s%d", s + 1, &x);
if(solve()) puts(ans + 1);
else puts("-1");
}
return 0;
}