AcWing 1070. 括号配对 区间dp
发布日期:2021-05-12 17:10:56 浏览次数:21 分类:精选文章

本文共 2711 字,大约阅读时间需要 9 分钟。

为了将给定的BE字符串转换为GBE字符串,我们需要添加最少的字符。GBE的定义类似于正确的括号匹配结构。我们可以使用动态规划来找出最长的GBE子串,然后计算在两侧添加最少的字符数。

方法思路

  • 问题分析:GBE的结构类似于正确的括号匹配。空表达式是GBE,如果两个字符串都是GBE,那么它们的组合也是GBE。我们需要找到最少添加字符使BE字符串成为GBE。

  • 动态规划:使用二维数组dp[i][j]表示子串s[i..j]是否是GBE。通过遍历所有可能的子串长度,检查括号配对情况,更新dp数组。

  • 扩展子串:找到最长的GBE子串,然后计算在两侧添加最少的字符数,使整个字符串成为GBE。

  • 解决代码

    #include 
    using namespace std;
    bool match(char a, char b) {
    return (a == '(' && b == ')') || (a == '[' && b == ']');
    }
    int main() {
    string s;
    cin >> s;
    int n = s.length();
    bool dp[n][n]; // dp[i][j] is true if s[i..j] is GBE
    int len = 0;
    // 初始化所有可能的子串长度
    for (int i = 0; i < n; ++i) {
    dp[i][i] = true; // 单个字符是空表达式,属于 GBE
    }
    for (int len_sub = 2; len_sub <= n; ++len_sub) {
    for (int i = 0; i <= n - len_sub; ++i) {
    int j = i + len_sub - 1;
    if (match(s[i], s[j])) {
    if (j - i == 1) {
    dp[i][j] = true;
    } else {
    dp[i][j] = dp[i+1][j-1];
    }
    } else {
    dp[i][j] = false;
    }
    }
    }
    // 找到最长的 GBE 子串
    int max_len = 0;
    for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
    if (dp[i][j]) {
    max_len = max(max_len, j - i + 1);
    }
    }
    }
    // 扩展到整个字符串
    bool can_be_gbe = dp[0][n-1];
    if (!can_be_gbe) {
    // 找最长的中心对称子串,并计算左右添加的字符数
    int best = 0;
    for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
    if (dp[i][j] && (j - i + 1) > best) {
    best = j - i + 1;
    }
    }
    }
    // 扩展左右
    int add_left = 0, add_right = 0;
    int min_add = INT_MAX;
    for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
    if (dp[i][j]) {
    int l = i, r = j;
    while (l > 0 && match(s[l-1], s[l])) {
    l--;
    }
    while (r < n-1 && match(s[r], s[r+1])) {
    r++;
    }
    int left = l - 0;
    int right = (n-1) - r;
    if (left + right < min_add) {
    min_add = left + right;
    }
    }
    }
    }
    cout << min_add << endl;
    return;
    } else {
    cout << 0 << endl;
    return;
    }
    }

    代码解释

  • 匹配函数match(a, b)检查字符ab是否是括号配对。

  • 动态规划数组初始化dp[i][j]表示子串s[i..j]是否是GBE。单个字符初始化为GBE。

  • 填充动态规划表:对于每个子串长度,检查括号配对情况,更新dp数组。

  • 寻找最长GBE子串:遍历所有子串,找出最长的GBE子串。

  • 扩展子串:如果整个字符串不是GBE,寻找最长的中心对称子串,并计算左右添加字符数的最小值。

  • 通过这种方法,我们可以高效地找到最少需要添加的字符数,使BE字符串转换为GBE字符串。

    上一篇:AcWing 1078. 旅游规划 树型dp(非常详细)
    下一篇:AcWing 1226. 包子凑数 背包dp+思维

    发表评论

    最新留言

    路过按个爪印,很不错,赞一个!
    [***.219.124.196]2025年04月20日 21时07分59秒