题目大意
给出一个01序列,现在每次能恰好翻转连续相同的 k k k个数,即 0 → 1 , 1 → 0 0 \rightarrow 1, 1 \rightarrow 0 0→1,1→0,给出两个序列问能否翻转有限次使得两个序列相互转换。
解题思路
观察样例一,还有如下两个序列:
010010
010010
010010
101101
101101
101101
我们发现是可以相互转换的!首先对于基础的连续 k k k个 1 1 1或者 0 0 0,可以直接翻转为 1 1 1,两边如果有不相同的数字,现在已经连成了一片相同的数字,然后可以操作这片相同的片段的任意位置翻转 k k k个。手玩可以发现,我们可以将两边不同的数字向中间传递,最后都消成相同的数字。这启发我们,无需考虑翻转的过程,只要能消完,无需考虑先消哪段,对于原序列已经存在的连续的 k k k个 0 , 1 0,1 0,1,可以看做是消消乐那样直接消去,然后两边又拼在一起,最后只需要看两个序列剩余部分是否相等。
//
// Created by Happig on 2020/11/11
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define ENDL "\n"
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;
stack<char> st1;
stack<int> st2;
void solve(string s, string &ans, int k) {
for (int i = 0; i < s.size(); i++) {
if (st1.empty()) st1.push(s[i]), st2.push(1);
else {
if (st1.top() == s[i]) {
++st2.top();
} else {
st1.push(s[i]);
st2.push(1);
}
if (st2.top() == k) {
st1.pop();
st2.pop();
}
}
}
while (!st1.empty()) {
int x = st2.top();
for (int i = 0; i < x; i++) ans += st1.top();
st1.pop();
st2.pop();
}
}
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, k;
string s, t;
cin >> n >> k;
cin >> s >> t;
if (k == 1) {
cout << "Yes" << ENDL;
return 0;
}
string s1 = "", s2 = "";
solve(s, s1, k);
solve(t, s2, k);
//cout << s1 << "+" << s2 << endl;
if (s1 == s2) cout << "Yes" << ENDL;
else cout << "No" << ENDL;
return 0;
}