【问题标题】:Flipping algorithm翻转算法
【发布时间】:2017-03-23 03:18:37
【问题描述】:

我有一个字符串 s 包含不同类型的括号:()[]。如何平衡这种类型的字符串与尽可能少的反转次数?我可以用任何其他支架替换任何支架。

例如:[)(] 的成本为 2,它变为 [()][](( 的成本为 1,它变为 []()[(]) 不平衡。

一个更复杂的例子:)[)([)())] 可以通过 4 次更改变为([])[(())],但也可以通过 3 步变为[()(()())],这是使其平衡的最少修改次数。

我该如何解决这个问题?

【问题讨论】:

  • 更换操作请详细说明。究竟什么可以代替什么?相同类型的括号可以互换吗?或者是否可以用相同类型的括号替换每个括号?
  • 可以将 "(" 替换为 ")","]","["。 ")" 通过 "(","]","[" 。 "[" 通过 "(",")","]" 。 "]" 通过 "(",")","["。 ,正如我所说,任何括号与任何其他括号。
  • 不确定我是否理解,你能添加一个测试用例(输入>输出)吗?
  • @AxelH,添加了一个。
  • )[)([)())]可以在3个步骤内修改[()(()())]

标签: string algorithm brackets balance


【解决方案1】:

我提出的第一种方法是O(n^3) 动态编程。

match(i, j) 成为您必须进行的替换次数,以便将s[i]s[j] 设置为()[]。所以match(i, j) 可以是012

考虑dp[i][j] = the minimum cost to balance the subsequence from i to j in your brackets array。现在您将dp[i][i + 1] 定义为:

dp[i][i + 1] = match(i, i + 1)

现在的一般规则是,对于任何i < p < j,我们在dp[i + 1][j - 1] + match(i, j)min(dp[i][j], dp[i][p] + dp[p + 1][j]) 之间取总最小值。显然,结果将保存在dp[1][n]。有一个 C++ 解决方案(我还将在大约 15 分钟内上传一个 python 程序,然后我将完成它 - python 不是那么强大:P)。

#include <iostream>
#include <string>
using namespace std;

int dp[100][100];
string s;
int n;

int match(char a, char b) {
    if (a == '(' && b == ')') {
        return 0;
    }
    if (a == '[' && b == ']') {
        return 0;
    }
    if ((a == ')' || a == ']') && (b == '(' || b == '[')) {
        return 2;
    }
    return 1;
}

int main() {
    cin >> s;
    n = s.length();
    s = " " + s;
    for (int i = 0; i <= n; ++i) {
        for (int j = 0; j <= n; ++j) {
            dp[i][j] = 0x3f3f3f3f;
        }
    }    

    for (int i = 1; i < n; ++i) {
        dp[i][i + 1] = match(s[i], s[i + 1]);
    }

    for (int k = 3; k <= n; k += 2) {
        for (int i = 1; i + k <= n; ++i) {
            int j = i + k;
            dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] + match(s[i], s[j]));
            for (int p = i + 1; p <= j; p += 2) {
                dp[i][j] = min(dp[i][j], dp[i][p] + dp[p + 1][j]);
            }
        }
    }
    cout << dp[1][n] << '\n';
    /*for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cout << dp[i][j] << ' ';
        }
        cout << '\n';
    }*/
    return 0;
}

编辑:

给你 Python :)

s = input()
n = len(s)
inf = 0x3f3f3f3f

def match(x, y):
    if x == '(' and y == ')':
        return 0
    if x == '[' and y == ']':
        return 0
    if (x == ')' or x == ']') and (y == '(' or y == '['):
        return 2
    return 1

# dp[i][j] = min. cost for balancing a[i], a[i + 1], ..., a[j]
dp = [[inf for j in range(n)] for i in range(n)]

for i in range(n - 1):
    dp[i][i + 1] = match(s[i], s[i + 1])

for k in range(3, n, 2):
    i = 0
    while i + k < n:
        j = i + k
        dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] + match(s[i], s[j]))
        for p in range(i + 1, j, 2):
            dp[i][j] = min(dp[i][j], dp[i][p] + dp[p + 1][j])
        i += 1

print(dp[0][n - 1])
#for i in range(n):
#    for j in range(n):
#        print(dp[i][j], end = ' ')
#    print()

【讨论】:

  • 太棒了,朋友!
猜你喜欢
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 2017-11-25
  • 2022-08-14
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多