题解 [CCPC2021 广州] Cafeteria
先来口胡一个做法:
发现 Dave 选菜的过程实际上是在原串中匹配一个子序列的过程
那么单次询问就有一个 DP:
令 \(f_{i, j}\) 为在原串中匹配到位置 \(i\),在模式串中匹配到位置 \(j\) 的方案数
做一次是 \(O(nm)\) 的
现在有多次询问,发现这个 DP 在一定程度上是可以拆开的
考虑扔到猫树上处理,对原串匹配到的位置进行分治
在每个分治区间,
令 \(f_{i, j, k}\) 为从 \(mid+1\) 到 \(r\),模式串从 \(i\) 开始匹配,原串匹配到位置 \(j\),模式串匹配到位置 \(k\) 的方案数
令 \(g_{i, j, k}\) 为从 \(mid\) 到 \(l\),模式串从 \(i\) 开始反向匹配,原串反向匹配到位置 \(j\),模式串反向匹配到位置 \(k\) 的方案数
那么预处理的复杂度是 \(O(m^2n\log n)\) 的,询问复杂度 \(O(tm)\)
然后正解:
这个 DP 实际上是可以矩阵乘法实现的
原串的每个字符形成了一个转移矩阵 \(T\)
\[T_k(i, i)=1
\]
\[T_k(i, i+1)=[s_k=t_{i+1}]
\]

这个矩阵最大的特点就是它有逆
那么问题就变成了怎么快速求逆和逆的前缀积