题意:
给你一个括号序列 $s$ 和一个数 $n$ ,让你求出长度为 $2 * n$ 并且 $s$ 是最后串里面的一个子串的合法括号序列有多少种。$mod (1e9 + 7)$。
分析:
先确定 $dp[i][j][k]$ 表示最后的串到第 $i$ 位,后缀匹配到长度为 $j$ 的原串,有 $k$ 个未匹配的左括号的方案数有多少个。
为什么要这样定义状态呢,如果只是单纯地定义 $dp[i][k]$ 的话,你不能够确定这些串里面是否含有 $s$(感觉是废话)。
那么转移就是:
$dp[i][j][k]$ $+=$ $\sum_{x}^{所有可能的后缀情况} dp[i - 1][k][x][看当前为是 ‘(‘ 还是 ‘)’,来决定]$
但是这样的转移好像很麻烦,我们换成
$dp[i][当前位填’(‘后对应的原串后缀长度][k + 1]$ $+=$ $dp[i - 1][j][k]$
$dp[i][当前位填’)’后对应的原串后缀长度][k]$ $+=$ $dp[i - 1][j][k + 1]$
是不是感觉很简单,然后这个 当前位填 ‘(‘ or ‘)’ 后对应的原串后缀长度 可以用 $KMP$ 的 $next$ 数组来优化,我直接预处理出来一个数组 $to[x][i]$ 表示当前串后缀已经和原串匹配了长度 $x$ ,接下来填 $‘(’$ $(i = 0)$,$‘)’$ $(i = 1)$ 后,后缀和原串对应的匹配长度。然后就可以愉快的 $dp$ 了。
当匹配到长度和原串相同时,就直接转移到 $len$ 统计答案。
最后答案就是 $dp[2 * n][len][0]$ 。
代码:
1 |
|