题意
给定一个仅包含'('、')'和'?'三种字符构成的字符串,'?'字符可以代替左括号或者右括号。请问该字符串可以代表多少种不同的合法括号序列?
思路
看基本上都写的dp,来个记忆化搜索的代码吧
每个?字符都有两种可能,填左括号或是填右括号,可以枚举填哪个进行记忆化搜索
如何判断是合法的括号序列?只需要维护左括号比右括号多了几个就可以,也就是当前没有配对的右括号个数。假设为val,如果当前是左括号,那么下一次dfs的参数肯定是val+1;如果当前是右括号,下一次dfs参数是val-1,表示可以配对一个左括号。注意这里其实会有不合法情况,就是其实左边是没有左括号的,也就是val为负数的情况,需要在dfs开始就判断下。
边界条件就是如果遍历完了所有的字符串,如果左括号和右括号一样多,就是合法的,返回1;否则,返回0
这里是从1到n写的记忆化搜索,也可以从n到1,一样的思路
注意取模
package main
import "fmt"
func main() {
/*
给定一个仅包含'('、')'和'?'三种字符构成的字符串,'?'字符可以代替左括号或者右括号。请问该字符串可以代表多少种不同的合法括号序列?
*/
const MOD = 1_000_000_007
var s string
fmt.Scan(&s)
n := len(s)
s = " " + s
var dfs func(int, int) int
/*
子问题:如果当前字符是?的话填什么 可以填左括号 也可以填右括号
两种选择
val表示没有配对的左括号数量
*/
dp := make([][]int, n+1)
for i := 1; i <= n; i ++ {
dp[i] = make([]int,n+1)
for j := 0; j <= n; j ++{
dp[i][j] = -1
}
}
dfs = func(idx int, val int) int {
if val < 0 {
return 0
}
if idx == n+1 {
//结束
if val == 0 {
return 1
} else {
return 0
}
}
if dp[idx][val] != -1 {
return dp[idx][val]
}
var res = 0
if s[idx] == '?' {
//这一位填(
res = (res + dfs(idx+1, val+1)) % MOD
//这一位填)
res = (res + dfs(idx + 1, val - 1 )) % MOD
}else if s[idx] == '(' {
res = dfs(idx+1,val+1)
}else{
res = dfs(idx+1,val-1)
}
dp[idx][val] = res
return res
}
fmt.Println(dfs(1,0))
}

京公网安备 11010502036488号