NOIP2024 编辑字符串
题目描述
小 M 有两个长度为 \(n\) 且字符集为 \(\{0,1\}\) 的字符串 \(s1,s2\)。
小 M 希望两个字符串中对应位置字符相同的出现次数尽可能多。
小 M 可以用工具对 \(s1\) 或 \(s2\) 进行多次字符交换,其中可以参与交换的字符能够交换任意多次。
现在小 M 想知道,在使用编辑工具后,两个字符串中对应位置字符相同的出现次数最多能有多少。
- 第四行包含一个长度为 \(n\) 且字符集为 \(\{0,1\}\) 的字符串 \(t1\),其中 \(t1_i\) 为 \(1\) 表示 \(s1_i\) 可以参与交换,反之不能。
- 第五行包含一个长度为 \(n\) 且字符集为 \(\{0,1\}\) 的字符串 \(t2\),其中 \(t2_i\) 为 \(1\) 表示 \(s2_i\) 可以参与交换,反之不能。
解决办法
-
第一步
对于 \(t\) 串中出现的 \(010\) 显然可以转换为 \(000\)。 -
第二步 处理连通块
保存 \(t\) 中每段连续的 \(1\) 的左端、右端、\(1\) 的个数、\(0\) 的个数。 -
第三步 分类讨论处理
分为- \(\{t1_i,t2_i\}=\{0,0\}\)
- \(\{t1_i,t2_i\}=\{1,0\}\)
- \(\{t1_i,t2_i\}=\{0,1\}\)
- \(\{t1_i,t2_i\}=\{1,1\}\)
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int rd()
{
int x = 0,w = 1;
char ch = 0;
while(ch < '0' || ch > '9')
{
if(ch == '-') w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
int T;
int n;
int sum1[N],sum2[N];
signed main()
{
// freopen("edit.in","r",stdin);
// freopen("edit.out","w",stdout);
T = rd();
while(T--)
{
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
int ans = 0;
n = rd();
string s1,s2,t1,t2;
cin >> s1 >> s2 >> t1 >> t2;
s1 = '0' + s1 + '0',s2 = '0' + s2 + '0',t1 = '0' + t1 + '0',t2 = '0' + t2 + '0';
int l,cnt1 = 0,cnt2 = 0;
for(int i = 1;i <= n;i++)
{
sum1[i] = sum1[i - 1] + (s1[i] - '0');
sum2[i] = sum2[i - 1] + (s2[i] - '0');
if(t1[i - 1] == '0' && t1[i + 1] == '0') t1[i] = '0';
if(t2[i - 1] == '0' && t2[i + 1] == '0') t2[i] = '0';
}
for(int i = 1;i <= n;i++)
{
if(t1[i] == t2[i] && t1[i] == '0' && s1[i] == s2[i]) ans++;
if((t1[i] == '1' || t2[i] == '1') && (t1[i - 1] == '0' && t2[i - 1] == '0'))
{
l = i - 1;
}
if((t1[i] == '1' || t2[i] == '1') && (t1[i + 1] == '0' && t2[i + 1] == '0'))
{
ans += i - l - abs((sum1[i] - sum1[l]) - (sum2[i] - sum2[l]));
}
}
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号