一个仅包含0
、1
、?
的字符串(其中?
为通配符),求它是否满足所有的字串均满足0
和1
的数量相等。
n
为字符串长度,k
为要求满足题意的字符串子串长度。
首先我们可(bu)以(neng)发现: s [ i ] = = s [ i % k ] s[i]==s[ i \% k ] s[i]==s[i%k] 。
这个还是比较好理解的:想象一个大小为k
的窗口从左向右滑动(就是滑动窗口啦),如果当前窗口内的字符串满足条件,那么当窗口向右滑动时,若之后的字符串也满足条件,则必然存在左边出去的字符等于右边进来的字符,即 s [ i ] = = s [ i % k ] s[i]==s[ i \% k ] s[i]==s[i%k]
如果不满足该等式则必然不能构造出满足条件的字符串。
此后我们只需要证明字符串s[0...k-1]
满足条件即可。为此,我们需要记录该字符串中0
和1
的数量,如果其中任意一个字符的数量大于k/2
,则不能构造出0
和1
的数量相等的字符串。
#include
using namespace std;
const int N = 3e5 + 10;
int cnt[N][2], n, k;
string s;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;cin >> T;
while (T--) {
memset(cnt, 0, sizeof(cnt));
cin >> n >> k;
cin >> s;
int size = s.size();
for (int i = 0; i < size; i++) {
if (s[i] == '0') cnt[i % k][0] +=1;
else if (s[i] == '1') cnt[i % k][1] += 1;
}
bool ans = true;
int cnt0 = 0, cnt1 = 0;
for (int i = 0; i < k; i++) {
if (cnt[i][0] > 0 && cnt[i][1] > 0) {
ans = false;
break;
}
if (cnt[i][0] > 0) {
cnt0++;
} else if (cnt[i][1] > 0) cnt1++;
}
if (cnt0 > k/2 || cnt1 > k/2) ans = false;
cout << (ans ? "YES" : "NO") << endl;
}
return 0;
}
这道题我用了三天时间,每天想一遍,虽然最后还是去搜题解了hhhhh,但是这个过程以及最后的AC所带来的快乐是以前稍有不会就去搜题解然后AC所不能比拟的。
我还很菜,但我会努力!
冲冲冲!
最后感谢这篇文章的作者,真的是醍醐灌顶!