括号匹配序列计数问题

题意

一个长度为 n 且符合规范的括号序列,其有些位置已经确定了,有些位置尚未确定,求这样的括号序列一共有多少个。要求复杂度为 O(n3)

分析

由题意可知,我们可以这样定义括号匹配序列:

  • 空序列是括号匹配序列。
  • 如果 S 是括号匹配序列,那么 (S) 也是括号匹配序列。
  • 如果 A 是括号匹配序列,B 是括号匹配序列,那么 AB 也是括号匹配序列。

这样的定义似乎很正确,但对于我们的计数却有不利影响,原因如下述。
首先定义状态 dp[l][r] 为区间 [l,r] 中括号匹配序列的数量,转移如下:

{dp[l][r]+=k=lrdp[l][k]dp[k+1][r]dp[l][r]+=dp[l+1][r1](s[l]==(&&s[r]==))

乍一看还挺正确的,其实不然。
比如对于这种情况:()()()。可以这样断开:()_()()。也可以这样断开:()()_()。然而这两种断开方式对应的括号匹配序列是一样的,因此就重算了。思考去重的方法,多少又有点无从下手,难道没有办法了吗?
思考一下刚才的dp对应的文法:

12S>(S)|()

3S>SS

可见,S 存在两种对应关系,这称作文法的二义性。这就导致我们算重复了。于是,切入点就变为如何设计文法,使其没有二义性。

比如下面的这种设计:

S>A|B

12A>()|(A)|(B)

3B>AB|AA

可见,新增了 AB 两种情况,使得不存在 AB 对应两种对应关系,这就消除了文法的二义性。只需要对 A B 这两种情况分别dp,最后将总和加起来即可。设 f[l][r] 为对 A 的 dp,g[l][r] 为对 B 的dp。转移如下:

{f[l][r]+=f[l+1][r1]+g[l+1][r1](s[l]==(&&s[r]==))g[l][r]=k=lrf[l][k](g[k+1][r]+f[k+1][r])

最后的答案就是 f[1][n]+g[1][n]
如此,通过对文法设计进行改变,就能极大地降低算法复杂度。类似的思路在P7914 [CSP-S 2021] 括号序列也有体现。


__EOF__

本文作者Never Gonna Give You Up!
本文链接https://www.cnblogs.com/CZ-9/p/17366186.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   腾云今天首飞了吗  阅读(265)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示