1. 问题解析:01子序列构造的核心逻辑
这道题目要求我们在一个01字符串中找到一个区间,使得该区间内恰好包含k个"01"子序列。首先我们需要明确几个关键概念:
子序列与子串的区别至关重要。子串是原字符串中连续的字符序列,而子序列只需保持相对顺序,不要求连续。例如在字符串"0011"中:
- "01"作为子串出现1次(第3-4字符)
- 但作为子序列出现4次(1-3,1-4,2-3,2-4)
题目要求的是统计子序列数量,这直接影响我们的解题思路。统计区间[l,r]内的"01"子序列数量,实际上就是统计该区间内每个'0'后面有多少个'1'的总和。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 双指针算法设计思路
2.1 基本思想
双指针算法通常用于处理数组/字符串的区间问题。在这道题中,我们维护一个滑动窗口[l,r],动态计算窗口内的"01"子序列数量:
- 当数量不足k时,向右移动r指针扩大窗口
- 当数量超过k时,向右移动l指针缩小窗口
- 当数量等于k时,立即返回当前区间
2.2 关键变量定义
- cnt0:当前窗口中'0'的数量
- cnt1:当前窗口中'1'的数量
- num:当前窗口中的"01"子序列数量
2.3 移动指针时的更新规则
当r指针右移遇到新字符时:
- 如果是'0':只增加cnt0(因为它后面还没有'1'与之配对)
- 如果是'1':增加num(它与前面所有'0'都能配对),同时增加cnt1
当l指针右移排除字符时:
- 如果是'0':减少num(它后面所有的'1'都不能与之配对了),同时减少cnt0
- 如果是'1':只减少cnt1
3. 算法实现详解
3.1 初始化处理
cpp复制LL n, k;
cin >> n >> k;
string s; cin >> s;
int cnt0 = 0, cnt1 = 0;
int l = 0, r = 0;
我们首先读取输入数据,初始化双指针都指向字符串起始位置(注意C++中字符串下标从0开始)。
3.2 主循环逻辑
cpp复制while (l < n && r < n) {
if (num == k) {
cout << l + 1 << ' ' << r + 1 << endl;
retu
