【问题标题】:Longest subsequence of S that is balancedS的最长平衡子序列
【发布时间】:2012-10-15 23:10:39
【问题描述】:

给定问题:

一串括号据说是 如果字符串中的左括号和右括号可以正确配对,则平衡。例如,字符串“(())”和“()()”都是平衡的,而字符串“(()(”)不是 均衡。
给定一个由括号组成的长度为 n 的字符串 S,假设您想找到平衡的 S 的最长子序列。使用动态规划,设计一种算法,在 O(n^3) 时间内找到 S 的最长平衡子序列。

我的做法:
假设给定字符串:S[1 2 ... n]
当 S[i] == ')' 时,有效的子序列可以在 S[i] 处结束,即 S[i] 是右大括号,并且在 S[i] 之前至少存在一个未使用的左大括号。这可以在 O(N) 中实现。

#include<iostream>
using namespace std;
int main(){
    string s;
    cin >> s;
    int n = s.length(), o_count = 0, len = 0;
    for(int i=0; i<n; ++i){
        if(s[i] == '('){
            ++o_count;
            continue;
        }
        else if(s[i] == ')' && o_count > 0){
            ++len;
            --o_count;
        }
    }
    cout << len << endl;
    return 0;
}

我尝试了几个测试用例,它们似乎运行良好。我在这里错过了什么吗?如果不是,那我该如何为这个问题设计一个 O(n^3) 动态规划解决方案?

这是我正在使用的subsequence 的定义。

谢谢!

【问题讨论】:

  • 您的程序为 ()() 返回 2,为 ()()(() 返回 3。两者都应该是 4。
  • @JohnKugelman - 为什么第二个不应该是6?如果他的程序返回对的数量,它会返回正确的结果 2。乘以 2 得到实际的字符串长度。
  • @IVlad 平衡的括号必须相邻。
  • @JohnKugelman - 我不确定你的意思。 ()()()()()(() 的长度为 6 (3*2) 的平衡子序列。它也是最长的平衡子序列,并且 OP 的程序正确地找到了它的(一半)长度。
  • 是的,返回值为否。适当平衡的最长子序列中的对。

标签: algorithm dynamic-programming


【解决方案1】:

对于O(n^3) DP,我认为这应该可行:

dp[i, j] = longest balanced subsequence in [i .. j]
dp[i, i] = 0
dp[i, i + 1] = 2 if [i, i + 1] == "()", 0 otherwise

dp[i, j] = max{dp[i, k] + dp[k + 1, j] : j > i + 1} in general

这可以类似于optimal matrix chain multiplication 的方式实现。

您的算法对我来说似乎也是正确的,例如这个问题:

http://xorswap.com/questions/107-implement-a-function-to-balance-parentheses-in-a-string-using-the-minimum-nu

解决方案与您的基本相同。

你只是忽略了额外的括号,所以我不明白为什么它不起作用。

【讨论】:

  • 是的,我也认为DP应该工作。感谢您提供的链接,我认为我在这种方法中遗漏了一些东西。
  • 这个答案不正确。考虑 (()),上面的算法返回 0 而它必须是 4。
  • @Nima - 没错!您不能应用相同的算法。在这种情况下,OP 的算法应该做得很好。不幸的是,我不能再删除这个答案了。
  • 你可以在这里找到这个问题的通用版本的答案:stackoverflow.com/questions/27583771/…
【解决方案2】:

这是一个O(n^2)Java 中的时空 DP 解决方案:

public int findLongestBalancedSubsequence(String seq, int n) {
    int[][] lengths = new int[n][n];

    for (int l = 1; l < n; l++) {
        for (int i = 0; i < n - l; i++) {
            int j = i + l;
            // Ends are balanced.
            if (seq.charAt(i) == '(' && seq.charAt(j) == ')') {
                // lengths[i, j] = max(lengths[i + 1, j - 1] + 2, lengths[i + 1, j] + 
                // lengths[i, j - 1] - lengths[i + 1, j - 1])
                if (lengths[i + 1][j - 1] + 2 > lengths[i + 1][j] +
                    lengths[i][j - 1] - lengths[i + 1][j - 1])
                    lengths[i][j] = lengths[i + 1][j - 1] + 2;
                else
                    lengths[i][j] = lengths[i + 1][j] +
                        lengths[i][j - 1] - lengths[i + 1][j - 1];
            // Ends are not balanced.
            } else {
                // lengths[i, j] = max(lengths[i + 1, j], lengths[i, j - 1])
                if (lengths[i + 1][j] > lengths[i][j - 1])
                    lengths[i][j] = lengths[i + 1][j];
                else
                    lengths[i][j] = lengths[i][j - 1];
            }
        }
    }

    return lengths[0][n - 1];
}

【讨论】:

  • 您能否对lengths[i, j] = max(lengths[i + 1, j - 1] + 2, lengths[i + 1, j] + lengths[i, j - 1] - lengths[i + 1, j - 1]) 做一些解释。谢谢。
猜你喜欢
  • 1970-01-01
  • 2015-02-19
  • 2021-01-06
  • 2017-03-02
  • 1970-01-01
  • 2017-02-25
  • 2014-07-16
  • 1970-01-01
相关资源
最近更新 更多