Naman has two binary strings s s s and t t t of length n n n (a binary string is a string which only consists of the characters “0” and “1”). He wants to convert s s s into t t t using the following operation as few times as possible.
In one operation, he can choose any subsequence of s s s and rotate it clockwise once.
For example, if s = 1110100 s=1110100 s=1110100, he can choose a subsequence corresponding to indices (11-based) { 2 , 6 , 7 } \left\{2,6,7\right\} {2,6,7} and rotate them clockwise. The resulting string would then be s = 1010110 s=1010110 s=1010110.
A string a a a is said to be a subsequence of string b b b if a a a can be obtained from b b b by deleting some characters without changing the ordering of the remaining characters.
To perform a clockwise rotation on a sequence c c c of size k k k is to perform an operation which sets c 1 : = c k , c 2 : = c 1 , c 3 : = c 2 , … , c k : = c k − 1 c_1:=c_k,c_2:=c_1,c_3:=c_2,…,c_k:=c_{k−1} c1:=ck,c2:=c1,c3:=c2,…,ck:=ck−1 simultaneously.
Determine the minimum number of operations Naman has to perform to convert s s s into t t t or say that it is impossible.
这是一道非常好的题。
首先对于 s i = t i s_i=t_i si=ti的部分我们不必进行处理,也就是说取子数列的时候可以略去它们。
那么对于剩下 s i ≠ t i s_i\not=t_i si=ti的部分怎么保证操作次数最小呢?
我们可以发现当子数列 0 , 1 0,1 0,1交替出现,即"01010…"或"10101…"时操作最优,因为当子数列出现连续多个 0 0 0或 1 1 1时,只有最左边的0或1得到了有效的替换,这和舍去这一段而仅取其一的效果是等价的。
因此,不断找出连续的交错数列直到符合配对;由于每个交错数列旋转一次后便可翻转,即成功配对,因此答案为交错数列的个数。
而怎么求交错数列的个数呢?我们如果把不匹配的 s i , t i s_i,t_i si,ti分别用:
s i = 1 , t i = 0 , c i : = 1 s_i=1,t_i=0,c_i:=1 si=1,ti=0,ci:=1
s i = 0 , t i = 1 , c i : = − 1 s_i=0,t_i=1,c_i:=-1 si=0,ti=1,ci:=−1
来表示的话,交错数列的个数就是最长一段 c i = 1 c_i=1 ci=1或最长一段 c i = − 1 c_i=-1 ci=−1的长度,这是因为对于连续的一段1或-1,它们不可能在同一段交错级数,而必须把它们拆开。
那么问题转化为最大连续子序列和和最小连续子序列和的绝对值得最大值。
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int n;
string s;
string t;
int c[1000001];
int main()
{
scanf("%d",&n);
cin >> s;
cin >> t;
int a = 0;
int b = 0;
for (int i = 0;i < s.size();i ++)
if (s[i] == '0')
a ++;
for (int i = 0;i < t.size();i ++)
if (t[i] == '0')
b ++;
if (a != b)
{
printf("-1");
return 0;
}
for (int i = 0;i < s.size();i ++)
if (s[i] == t[i])
c[i] = 0;
else if (s[i] == '1')
c[i] = 1;
else c[i] = -1;
int ans = 0;
int now = 0;
for (int i = 0;i < s.size();i ++)
{
now = max(c[i],now + c[i]);
ans = max(ans,now);
}
now = 0;
int ans2 = 0;
for (int i = 0;i < s.size();i ++)
{
now = min(c[i],now + c[i]);
ans2 = min(ans2,now);
}
ans = max(-ans2,ans);
printf("%d",ans);
return 0;
}