#P2962. 第3题-小苯的字符串
-
1000ms
Tried: 9
Accepted: 7
Difficulty: 4
所属公司 :
阿里
时间 :2025年5月17日-阿里淘天(开发岗)
-
算法标签>模拟
第3题-小苯的字符串
题面描述
小苯有一个长度为 n 的 01 串 x(下标从 1 到 n),格格有一个长度恰好为 n−1 的 01 串 y(下标从 1 到 n−1)。要求在修改尽可能少的 x 串字符后,使其满足以下匹配规则:
- 若 yi=1,则必须有 xi=xi+1;
- 若 yi=0,则必须有 xi=xi+1。
一次修改操作是选择一个位置 i(1≤i≤n),令 xi:=xi⊕1。求最少需要多少次修改才能使匹配成立。
问题本质分析
上述匹配规则实际上把 x 串的相邻关系完全“锁定”下来:
- 如果我们确定了 x1,那么根据每个 yi,就能“递推”出整条目标串 t:ti+1=ti⊕yi(1≤i≤n−1).
- 因此,所有满足要求的 x 串只有 两种可能:
- 假设 t1=0,按上式生成一条串;
- 假设 t1=1,按上式生成另一条串。
- 对这两种候选串分别计算与原串 x 在对应位置的不同个数,取最小值即为答案。
解题思路
- 读入 n,x,y;
- 枚举两种初始值:t1=0 和 t1=1。
- 对于每一种,按规则构建目标串 t,并用一个计数器统计位置 i 上 xi=ti 的次数;
- 最后输出两种情况中的最小值。
此方法时间复杂度 O(n),空间复杂度 O(1) 或 O(n)(若显式存储 t 串)。
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
string x, y;
cin >> x >> y;
// 统计以 t1=0 和 t1=1 的差异次数
long long diff0 = 0, diff1 = 0;
// cur0 表示当前 t_i 当 t1=0 时的值;cur1 表示当 t1=1 时的值
int cur0 = 0, cur1 = 1;
// 遍历所有位置
for (int i = 0; i < n; i++) {
// 比较 x[i] 与 cur0/cur1
if (x[i] - '0' != cur0) diff0++;
if (x[i] - '0' != cur1) diff1++;
// 如果不是最后一个位置,则根据 y[i] 更新下一位
if (i < n - 1) {
int v = y[i] - '0';
cur0 ^= v;
cur1 ^= v;
}
}
// 最少修改次数
cout << min(diff0, diff1) << "\n";
}
return 0;
}
Python
import sys
input = sys.stdin.readline
def solve():
T = int(input())
for _ in range(T):
n = int(input())
x = input().strip()
y = input().strip()
diff0 = 0 # 初始 t1 = 0
diff1 = 0 # 初始 t1 = 1
cur0, cur1 = 0, 1
for i in range(n):
if int(x[i]) != cur0:
diff0 += 1
if int(x[i]) != cur1:
diff1 += 1
if i < n - 1:
v = int(y[i])
cur0 ^= v
cur1 ^= v
print(min(diff0, diff1))
if __name__ == "__main__":
solve()
Java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
int n = Integer.parseInt(br.readLine());
String x = br.readLine().trim();
String y = br.readLine().trim();
long diff0 = 0, diff1 = 0;
int cur0 = 0, cur1 = 1;
for (int i = 0; i < n; i++) {
int xi = x.charAt(i) - '0';
if (xi != cur0) diff0++;
if (xi != cur1) diff1++;
if (i < n - 1) {
int v = y.charAt(i) - '0';
cur0 ^= v;
cur1 ^= v;
}
}
System.out.println(Math.min(diff0, diff1));
}
}
}
题目内容
小苯有一个长度为n的01串x(下标从1到n),巧合的是格格也有一个长度恰好为n−1的01串y。(下标从1到n−1)
据说,格格的字符串y是用来匹配小苯的字符串x的,具体来说:
如果yi=1(1≤i≤n−1),则意味着必须有:xi=xi+1。
如果yi=0(1≤i≤n−1),则意味着必须有:xi=xi+1。
而现在小苯的串x并不一定满足y串的匹配要求,因此格格希望小苯修改尽可能少的字符,使得匹配成立,请你帮小苯算一算至少需要修改多少个字符吧。
修改:选择i(1≤i≤n),执行:xi:=xi⊕1(其中⊕表示按位异或运算。)
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≦T≦100)代表数据组数,每组测试数据描述如下:
第一行输入一个正整数 n(2≦n≤106)代表串的长度。
第二行输入一个长度为n,仅由字符‘0’和'1'构成的字符串x。
第三行输入一个长度为n−1,仅由字符'0'和'1'构成的字符串y
除此之外,保证单个测试文件的n之和不超过106
输出描述
对于每组测试数据: 在单独的一行输出一个整数,表示最少的修改次数。
样例1
输入
2
8
11001011
1000111
6
101010
1111
输出
4
0
说明
对于第一组测试数据,我们修改串为:“10000101”即可,需要至少4次修改操作。
对于第二组测试数据,我们不需要修改,因非输出0即可。