括号序列的最小合法化:区间动态规划与路径记录
作者:Mr木木木木_823 | 来源:互联网 | 2024-12-23 11:50
问题描述:通过添加最少数量的括号,使得给定的括号序列变为合法,并输出最终的合法序列。数据范围:字符串长度不超过100。涉及算法:区间动态规划(IntervalDP)。
### 问题描述
我们需要解决的问题是:给定一个由括号组成的序列,通过添加最少数量的括号,使其成为一个合法的括号序列,并输出该合法序列。合法括号序列是指每个左括号都有对应的右括号匹配,且匹配关系正确。
#### 数据范围
- 字符串长度 n 不超过 100。
### 涉及算法
本题主要使用区间动态规划(Interval DP)来解决。区间DP是一种特殊的动态规划方法,适用于处理区间上的问题,通过逐步扩大区间的范围来更新状态。
### 解题思路
我们定义 dp[i][j] 表示将区间 [i, j] 内的括号序列变成合法序列所需的最少添加括号数。具体的状态转移方程如下:
1. **初始化**:对于单个字符的区间,如果该字符是左括号或右括号,则需要添加一个对应的右括号或左括号。
2. **状态转移**:对于区间 [i, j],我们有两种情况:
- 如果 s[i] 和 s[k] 是一对匹配的括号(例如 '(' 和 ')' 或 '[' 和 ']'),则可以将区间 [i+1, k-1] 和 [k+1, j] 分别处理,此时 dp[i][j] = dp[i+1][k-1] + dp[k+1][j]。
- 如果没有找到匹配的括号,则直接在 s[i] 处添加一个对应的括号,dp[i][j] = dp[i+1][j] + 1。
3. **路径记录**:为了输出最终的合法序列,我们需要记录路径信息。path[i][j] 记录了区间 [i, j] 内匹配的括号位置。
### 代码实现
以下是完整的 C++ 实现代码:
```cpp
#include
using namespace std;
const int N = 105;
char s[N];
int dp[N][N], path[N][N];
void print(int l, int r) {
if (l > r) return;
if (path[l][r] == -1) {
if (s[l] == '(' || s[l] == ')') printf("()");
else printf("[]");
print(l + 1, r);
} else {
printf("%c", s[l]);
print(l + 1, path[l][r] - 1);
printf("%c", s[path[l][r]]);
print(path[l][r] + 1, r);
}
}
int main() {
while (~scanf("%s", s)) {
int n = strlen(s);
memset(dp, 0, sizeof(dp));
for (int len = 1; len <= n; len++) {
for (int i = 0, j = i + len - 1; j dp[i][j] = dp[i + 1][j] + 1; // s[i] 需要匹配一个括号
path[i][j] = -1; // 记录路径
for (int k = i + 1; k <= j; k++) { // 小序列更新大序列
if ((s[i] == '(' && s[k] == ')') || (s[i] == '[' && s[k] == ']'))
if (dp[i][j] > dp[i + 1][k - 1] + dp[k + 1][j]) {
dp[i][j] = dp[i + 1][k - 1] + dp[k + 1][j];
path[i][j] = k; // 记录路径
}
}
}
}
print(0, n - 1);
printf("\n");
}
return 0;
}
```
推荐阅读
-
本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ...
[详细]
蜡笔小新 2024-12-22 18:57:48
-
本文介绍了一种通过深度优先搜索(DFS)和质因数分解来解决最长树链问题的方法。我们通过枚举树链上的最大公约数(GCD),将所有节点按其质因子分类,并计算每个类别的最长链,最终求得全局最长链。 ...
[详细]
蜡笔小新 2024-12-23 11:59:34
-
-
本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ...
[详细]
蜡笔小新 2024-12-22 14:36:54
-
反向投影技术主要用于在大型输入图像中定位特定的小型模板图像。通过直方图对比,它能够识别出最匹配的区域或点,从而确定模板图像在输入图像中的位置。 ...
[详细]
蜡笔小新 2024-12-23 12:24:22
-
本文详细介绍了C++中map容器的多种删除和交换操作,包括clear、erase、swap、extract和merge方法,并提供了完整的代码示例。 ...
[详细]
蜡笔小新 2024-12-23 08:29:59
-
本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ...
[详细]
蜡笔小新 2024-12-22 20:15:25
-
本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ...
[详细]
蜡笔小新 2024-12-22 12:03:31
-
本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ...
[详细]
蜡笔小新 2024-12-22 11:44:35
-
本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ...
[详细]
蜡笔小新 2024-12-22 00:08:06
-
在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ...
[详细]
蜡笔小新 2024-12-21 18:13:59
-
本问题探讨了在特定条件下排列儿童队伍的方法数量。题目要求计算满足条件的队伍排列总数,并使用递推算法和大数处理技术来解决这一问题。 ...
[详细]
蜡笔小新 2024-12-23 12:18:55
-
本文介绍了一个SQL Server自定义函数,用于从字符串中提取仅包含数字和小数点的子串。该函数通过循环删除非数字字符来实现,并附带创建测试表、存储过程以演示其应用。 ...
[详细]
蜡笔小新 2024-12-23 10:16:49
-
题目描述:给定一个N*M的网格,初始时网格中有k个芯片,每个芯片的位置已知。玩家可以在每一步操作中将所有芯片沿同一方向移动一格。如果芯片到达边界,则保持不动。目标是通过一系列操作,使每个芯片依次访问指定的目标位置。 ...
[详细]
蜡笔小新 2024-12-22 17:38:34
-
本题要求实现一个函数,用于检查给定的字符串是否为回文。回文是指正向和反向读取都相同的字符串。例如,“XYZYX”和“xyzzyx”都是回文。 ...
[详细]
蜡笔小新 2024-12-22 16:59:05
-
本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ...
[详细]
蜡笔小新 2024-12-21 17:42:25
-
Mr木木木木_823
这个家伙很懒,什么也没留下!