NOIP 2015 子串 题解

分析

看题目有点像整数划分的感觉,但是区别在于,这个可以选择不连续的子串,而且需要匹配指定目标。
按照匹配的常规做法,还是采用线性顺序,逐个字符延伸。
定义 \(f[i][j][k][x]\) 表示字符串 A 前 i 位,用了 j 段,匹配到字符串 B 的前 k 位,用(x=1)或不用(x=0)a[i],所对应的方案数。

  • 如果 a[i] 与 b[k] 不相等:
    那么 a[i] 用不上,即 f[i][j][k][1] = 0。
    那么不用 a[i] 的话,那就是让前 i-1 个去做匹配,即 f[i][j][k][0] = f[i-1][j][k][0] + f[i-1][j][k][1]。
  • 如果 a[i] 等于 b[k]:
    如果不用 a[i],依旧是 f[i][j][k][0] = f[i-1][j][k][0] + f[i-1][j][k][1];
    如果用 a[i],那么 a[i] 与 b[k] 配对,剩下的去匹配。但是 a[i] 既可以单独成为一段,方案数对应 f[i-1][j-1][k-1][0] + f[i-1][j-1][k-1][1];
    也可以作为前面一段的一部分(必须保证前面一段是以 a[i-1] 结尾),对应方案数为 f[i-1][j][k-1][1]
  • 初始化问题
    我们要保证枚举的每个 i 的时候,当 a[i] 能够与 b[1] 配对的时候都会从 f[i-1][0][0][0] 推过来得到方案数,所以要保证所有的 f[i][0][0][0] 初始值为 1。

由于数据范围较大,直接思维数组有点困难,转移方程第一维可以看出,只跟上一阶段有关,因此可以滚动数组搞它。

代码就不写了,循环嵌套就行了。

posted @ 2020-07-05 11:02  狂飙霹雳虎  阅读(224)  评论(0编辑  收藏  举报