18北邮计算机院-D.最长平衡子串 //哈希+贪心

本文详细介绍了一种高效算法,用于解决给定只含0和1的字符串中寻找最长平衡子串的问题。通过将0视为-1并计算前缀和,利用哈希表记录和值首次出现的位置,实现了快速查找最长平衡子串的长度。适用于字符串长度最大为10^6的情况。

题目描述
给定只含01的字符串,找出最长平衡子串的长度(平衡串:包含0和1的个数相同),串长最大10^6

输入

 一个字符串,只包含01,长度不超过1000000

输出

 一行一个整数,最长的0与1的个数相等的子串的长度。

 

示例输入

3
1011
1111
1010

示例输出

2
0
4

思路:将0看做-1,求前i项和,当前i项和为0时,以此元素为结尾的最长长度为当前下标值+1;若该和值是第一次出现用hash数组记录该和值第一次出现时的下标i,否则当前下标值与hash数组中记录的当前和值第一次的下标值相减就是以此元素为结尾的最长长度。其中的最长的长度便是所要求的解。

实现代码:

#include<bits/stdc++.h>
using namespace std;
char s[1000003];
int h[2000003];
int main()
{
	int t,i,j;
	int m=1000001;//作为和值偏移值 防止出现负数无法用hash数组保存
	scanf("%d",&t);
	while(t--)
	{
	
		memset(h,-1,sizeof(h));
		scanf("%s",&s);
		int n=0,ma=0;
		for(i=0;i<strlen(s);i++)
		{
			if(s[i]=='0')n--;
			else n++;
			
			if(n==0)ma=max(ma,i+1);
			else if(h[n+m]==-1)h[n+m]=i;
			else {
				ma=max(ma,i-h[n+m]);	
			}
		}
		printf("%d\n",ma);
	}
}

 

<think>我们参考用户给出的find函数格式说明:`【字符串对象.find(子串/字符, 起始位置)】`,来介绍replace函数的使用格式。 根据之前的详细说明,replace函数有多种重载形式,但最核心的是通过位置和长度来指定替换区间,然后替换为新的内容。 我们可以将replace函数的使用格式概括如下(参考用户要求的格式): 基本格式:`字符串对象.replace(起始位置, 替换长度, 新内容)` 此外,还有一种类似于find函数中指定子串范围的形式:`字符串对象.replace(起始位置, 替换长度, 源字符串, 源字符串起始位置, 源字符串长度)` 因此,我们可以这样描述: ### C++字符串 `replace` 函数使用格式 #### 1. **基础替换格式** ```cpp 字符串对象.replace(替换起始位置, 被替换子串长度, 新内容); ``` - **参数说明**: - `替换起始位置`:从0开始计算的索引位置,指定从字符串的何处开始替换。 - `被替换子串长度`:指定要从原字符串中删除多少个字符。 - `新内容`:替换进去的字符串,可以是字符串对象、C风格字符串或重复的字符序列。 #### 2. **使用子串替换的格式(类似`find`的格式)** ```cpp 字符串对象.replace(替换起始位置, 被替换子串长度, 源字符串, 源字符串起始位置, 源字符串长度); ``` - **参数说明**: - 前两个参数同上。 - `源字符串`:提供替换内容的字符串。 - `源字符串起始位置`:从源字符串的哪个位置开始取子串- `源字符串长度`:从源字符串中取多长的子串。 #### 示例代码 ```cpp #include <iostream> #include <string> using namespace std; int main() { string s = "Hello world!"; // 基础替换:将"world"替换为"there" s.replace(6, 5, "there"); // 从位置6开始,替换5个字符(即"world")为"there" cout << s << endl; // 输出: Hello there! string source = "ABCDEFGHIJK"; // 使用源字符串的子串进行替换:取源字符串中位置2开始的3个字符(即"CDE")替换"there" s.replace(6, 5, source, 2, 3); cout << s << endl; // 输出: Hello CDE! } ``` #### 注意事项 - **位置有效性**:起始位置必须在字符串的有效范围内(0到字符串长度-1),否则会抛出`out_of_range`异常。 - **长度截断**:如果指定的替换长度超过了字符串从起始位置到末尾的长度,则只会替换到字符串末尾。 - **性能考虑**:替换操作可能引起字符串内存的重新分配,特别是当新内容比被替换的内容长很多时。 #### 与`find`函数的对比 | 函数 | 格式 | 作用 | |---------|------------------------------------------|--------------| | `find` | `字符串对象.find(子串/字符, 起始位置)` | 查找子串位置 | | `replace`| `字符串对象.replace(起始位置, 长度, 新内容)` | 替换子串 | > 💡 **提示**:通常先使用`find`函数定位子串,再使用`replace`进行替换,实现查找替换功能。 §§相关问题§§ 1. 如何用`replace`函数实现字符串中所有指定子串的替换?[^2] 2. 在替换操作中如何避免`out_of_range`异常? 3. `replace`函数能否用于替换单个字符?效率如何?</think>### C++ 字符串 `replace` 函数使用格式详解(参考 `find` 函数格式) #### 核心格式说明 ```cpp 字符串对象.replace(起始位置, 替换长度, 新内容); ``` - **起始位置**:替换开始的索引(从0开始),类型为 `size_t` - **替换长度**:原字符串中被删除的字符数,类型为 `size_t` - **新内容**:替换的字符串(支持多种类型) #### 常用重载格式(类比 `find`) | 功能场景 | 函数格式 | 类比 `find` 格式 | |------------------------|--------------------------------------------------------------------------|--------------------------------| | **基础替换** | `replace(pos, len, string)` | `find(str, pos)` | | 替换为C字符串 | `replace(pos, len, const char*)` | `find("str", pos)` | | 替换为重复字符 | `replace(pos, len, n, char)` | `find(char, pos)` | | **子串替换** | `replace(pos, len, src_str, subpos, sublen)` | `find(str, pos)` | | 迭代器范围替换 | `replace(iter_start, iter_end, new_str)` | 无直接对应 | > 💡 设计逻辑:与 `find(子串, 起始位置)` 类似,`replace` 通过 **位置+长度** 定位操作区间[^1] #### 示例代码详解 ```cpp #include <string> using namespace std; int main() { string s = "C++ is hard"; // 基础替换(类似 find 的位置参数) s.replace(4, 2, "not"); // "C++ not hard"(替换位置4开始的2字符) // 子串替换(类似 find 的子串定位) string src = "PythonJava"; s.replace(0, 3, src, 6, 4); // "Javanot hard"(取src[6]开始的4字符) // 结合 find 实现智能替换 size_t pos = s.find("hard"); if(pos != string::npos) { s.replace(pos, 4, "easy"); // "Javanot easy" } } ``` #### 关键特性说明 1. **位置验证**:起始位置需满足 $0 \leq \text{pos} < \text{length()}$,否则抛出 `out_of_range` 2. **长度自适应**:若 $\text{pos} + \text{len} > \text{length()}$ 自动截断到末尾 3. **返回值**:返回字符串对象的引用(支持链式调用) 4. **复杂度**:$O(n)$,其中 $n$ 是新内容的长度 #### 与 `find` 的对比 | 特性 | `find` 函数 | `replace` 函数 | |--------------|--------------------------------------|-------------------------------------| | **操作目的** | 定位子串 | 修改内容 | | **参数逻辑** | `(子串, 起始位置)` | `(起始位置, 长度, 新内容)` | | **返回值** | 位置索引(`size_t`)或`npos` | 字符串引用 | | **安全性** | 无效位置返回`npos` | 无效位置抛出异常 | > ⚠️ **注意**:`replace` 会直接修改原字符串,而 `find` 仅查询不修改[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值