dp套dp
奇怪的东西,感觉好暴力,难搞。
dp套dp,指把一个dp的dp数组当下标,去进行dp。就挺离谱。
例题:[TJOI2018]游园会
求长度为 n,字符集为 N,O,I,不包含子串 NOI 的字符串中,与给定字符串 S 的 LCS 为 len 的字符串数量。
首先先看怎么求 LCS 。令 B 串为模板串。
定义 f[i][j] 为A串前i个字符匹配了B串前j个字符时候的最长公共子序列。
可以得到 \(f[i][j] = \max(f[i-1][j],f[i][j-1],f[i-1][j-1] + [A[i] == B[j]])\)
也就是说,我们拿到一个数组 f ,f[i] 为匹配到 B 串前 i 个的最长公共子序列,已知 B 串,给接上一个字符 c ,可以dp出下一个 f 。
也就是看起来像是一个自动机,自动机的节点是一个 f 数组,f->f'连边相当于加上这个字符可以将 f 更新成 f'
我们可以将所有的f转移都先预处理出来,会发现有很多无用状态,发现f必然是递增的,并且相邻元素差值不大于一,差分后二进制压缩一下保存。
进行dp,设 dp[i][j][k] 为匹配到A串第i个字符,当前f状态为j,‘NOI’匹配到第 k 个。枚举下一个匹配的字符进行转移即可。