【Codeforces Round #668 (Div. 2) C】Balanced Bitstring

题目链接

点我呀

翻译

给你一个长度为 \(n\) 的字符串,让你判断这个字符串中是否每个长度为 \(k\) 的子串中 \(0\)\(1\) 的个数都相同

这个字符串中只会包含 \(0\)\(1\) 还有 ?, 这里的 ? 是通配符。

题解

\(k=4\) 为例子, 假设 s[1..4] 是符合要求的, 那么我们紧接着看 s[2..5],不难发现。

s[2..5] 也满足要求的话,必然有 s[1]==s[5]。因为, 整个字符串相当于少了一个 s[1] 然后多了一个 s[5]

所以有,对于任意的 \(i\)\([0..n-k]\)s[i] = s[i+k]

那么我们只需要看 \(s[0..k-1]\) 这一段就好了,对于 \(i\)\([0..k-1]\),应该有 \(s[i]=s[i+k]=s[i+2*k]=...\)

那么对于 \(i,i+k,i+2*k...\) 这些字符要么全为 \(0\) (对于这样的 \(i\) 记录为 \(cnt0\) ) 要么全为 \(1\) (对于这样的 \(i\) 记录为 \(cnt1\)), 或者全是问号 (如果某个 \(i\) 里面有 \(0\) 又有 \(1\), 则直接无解)。

如果 \(cnt0\)\(cnt1\) 的值都小于 \(k/2\),说明可以用全是问号的 \(i\) 进行补充使得 \(s[0..k-1]\) 这一段满足要求,即 \(0\)\(1\) 的个数相同 (否则,无法凑够 \(0\)\(1\) 一样,同样无解)。

只要第一段满足要求了,根据我们上面的 \(deduce\), 后面的所有长度为 \(k\) 的子串肯定也是满足要求的。

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 3e5;

int n, k, cnt[N + 10][2];
string s;

int main(){
    #ifdef LOCAL_DEFINE
        freopen("E://9.AlgorithmCompetition//Visitor.txt","r",stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    int T;
    cin >> T;
    while (T--){
        for (int i = 0;i < k; i++){
            cnt[i][0] = cnt[i][1] = 0;
        }
        cin >> n >> k;
        cin >> s;
        for (int i = 0;i < n; i++){
            if (s[i] == '0'){
                cnt[i%k][0]++;
            }else if (s[i] == '1'){
                cnt[i%k][1]++;
            }
        }
        bool ok = true;
        int cnt0 = 0,cnt1 = 0;
        for (int i = 0;i < k; i++){
            if (cnt[i][0] > 0 && cnt[i][1] > 0){
                ok = false;
                break;
            }else{
                if (cnt[i][0] > 0){
                    cnt0++;
                }else if (cnt[i][1] > 0){
                    cnt1++;
                }
            }
        }
        if (cnt0 > k/2 || cnt1 > k/2){
            ok = false;
        }
        if (ok){
            cout <<"YES"<< endl;
        }else{
            cout <<"NO"<<endl;
        }
    }
    return 0;
}
posted @ 2020-09-07 21:43  AWCXV  阅读(148)  评论(0编辑  收藏  举报