I.导入

求长度为\(\text{len}\)的包含给定连续子串\(\text{T}\)的 0/1 串的个数。(\(|T|<=15\))

通常来说这种题目应该立刻联想到状压 DP 与取反集——这样就不用考虑大量重复情况的容斥问题。设\(f_{i,S}\)表示前\(i\)个字符、最后\(|T|\)个字符为\(S\)、不包含给定连续子串的情况数,状态转移方程简单不述。时间复杂度 \(\Theta(2^{|T|}\text{len})\)。

II.巧妙利用利用失配树的序列DP

上述算法的时间复杂度相当高昂,当\(\text{T}\)十分大或者不是一个 0/1 串而是一个字符串的时候完全不可做,并且大量的状态是无用的,因为我只关心不出现给定的字符串,然而相当多的状态不用转移已经注定了不可能出现给定字符串,用状态压缩表示表示整段的完整状态非常亏本。重磅的优化来了:

我们在 DP 状态的设置上模拟 KMP 算法的过程。设\(f_{i,j}\)表示前\(i\)个字母、已经匹配到了模式串的\(j\)时有多少种情况。那么状态转移也依照 KMP 算法:枚举当前点的\(j\)并枚举下一个点填的字符,在失配树上找到下一个点的\(j\),把\(f\)累加过去,时间复杂度\(\Theta(\text{len}|T|^2s)\),其中\(s\)是字符种类数。

当然不止可以在模式串上加强,还可以在文本串上加强:当\(\text{len}\)是天文数字的时候,我们完全可以用矩阵快速幂优化上述过程,时间复杂度是\(log\)的。

III.例一:诗人小 K

\(n \le 40\),\(1 \le x,y \le 5\),\(1 \le y \le 7\)。

反集转换肯定是要想到的,但是到了这一步后状态设置完全无法下手,三段的序列和你设什么状态都不是。注意到三段和的大小都非常小,连续的这么三段的长度的总数都非常少,总数只有\(2^{4+6+4}\)个。那么我们这些模式串全部枚举出来,问题就转化为不出现这些字串的字符串的个数。把模式串丢进一个 Trie 里面建出 AC 自动机,然后把每个终止点在失配树中的子树的结点都打上标记——不可转移,然后就跟上题一模一样了。

IV.例二:P3290 [SCOI2016]围棋

考虑这东西有了两列怎么办。我们使用一种巧妙的轮廓线 DP:设\(f_{i,j,S,x,y}\)表示到了点\((i,j)\)、轮廓线上的状态是\(\text{S}\)、当前行与模式串的第一行匹配到\(x\)、与第二行匹配到\(y\)时的方案数。轮廓线的状态由 0/1 组成,表示它的后缀是否能够与模式串的第一行完全匹配。状态转移方程显然,前两维可以滚动掉,后面的维度需要大量的 memset (大概二十亿?),所以还是会超时。解决办法是把所有变量和数组都放进 register,这样刷表的速度就可以上天。这种解法就是这题目前的最优解法了。

V.总结

处理包含一种模式串的字符串总数,应该转化为求不包含它的字符串数,这个问题可以用 KMP 的思想大大优化。

一类巧妙利用利用失配树的序列DP的更多相关文章

  1. BSOJ 5445 -- 【2018雅礼】树 prufer序列 dp

    BSOJ在哪我也不知道 没有链接. 对于有标号无根树的统计和有度数限制 一般采用prufer序列. 根据prufer序列 容易知道 某个点的出现次数+1为当前点的度数. 对于这道题 考虑设f[i][j ...

  2. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

  3. 【字符串】【P5830】 【模板】失配树

    [字符串][P5830] [模板]失配树 Description 给定一个长度为 \(n\) 的字符串 \(S\),有 \(m\) 次询问,每次询问给定 \(S\) 的两个前缀,求它们的最长公共 bo ...

  4. [Codeforces261D]Maxim and Increasing Subsequence——树状数组+DP

    题目链接: Codeforces261D 题目大意:$k$次询问,每次给出一个长度为$n$的序列$b$及$b$中的最大值$maxb$,构造出序列$a$为$t$个序列$b$连接而成,求$a$的最长上升子 ...

  5. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  6. Codeforces Round #278 (Div. 1) Strip (线段树 二分 RMQ DP)

    Strip time limit per test 1 second memory limit per test 256 megabytes input standard input output s ...

  7. hdoj5909 Tree Cutting(点分治+树上dp转序列dp)

    题目链接:https://vjudge.net/problem/HDU-5909 题意:给一颗树,结点带权值v[i]<m.求异或和为k的子树个数(0<=k<m). 思路: 首先点分治 ...

  8. 72. Edit Distance(困难,确实挺难的,但很经典,双序列DP问题)

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...

  9. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

随机推荐

  1. 【Java虚拟机11】线程上下文类加载器

    前言 目前学习到的类加载的知识,都是基于[双亲委托机制]的.那么JDK难道就没有提供一种打破双亲委托机制的类加载机制吗? 答案是否定的. JDK为我们提供了一种打破双亲委托模型的机制:线程上下文类加载 ...

  2. Alpha-功能规格说明书

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-功能规格说明书 一.引言 1. 项目简介 项目团队:删库跑路对不队 项目名称:题士 项目内容 ...

  3. 笔记本加装SSD并装系统

    1,首先了解笔记本配置信息 一般加装SSD都是120~256左右,并使用原有的机械硬盘:首先确定加装位置:1,是否支持M.2接口:假如支持,可以直接购买,拆机装上:我的笔记本不支持:所以考虑2,光驱的 ...

  4. DDR3 IP和CIC IP仿真问题解决记录

    1.更新vivado的仿真库(data/secureip和verilog和vhdl文件夹)至最新的vivado库和生成IP的版本匹配: 2.vcs编译脚本里面把仿真库地址指向匹配的仿真库版本: 3.v ...

  5. populating-next-right-pointers-in-each-node-ii leetcode C++

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  6. hdu 2058 The sum problem(简单因式分解,,)

    Problem Description Given a sequence 1,2,3,......N, your job is to calculate all the possible sub-se ...

  7. prometheus(7)之数据类型与PromQL语法

    Prometheus的四种数据类型 counter (只增不减 计数) Gauge (常规数值 可变化大小) histogram (柱状图 小于上边界的 总数与次数) summary (分位数  小于 ...

  8. Allure 生成测试报表

    Allure官方文档参考地址:https://docs.qameta.io/allure/#_testng 1.在maven中添加依赖并进行相应的配置: <!-- 实现版本控制 --> & ...

  9. 用 Node.js 实现的最简单的 HTTP 服务器

    用 Node.js 实现的最简单的 HTTP 服务器 //app.js var http = require('http'); http.createServer(function(req, res) ...

  10. mysql查询报错this is incompatible with sql_mode=only_full_group_by

    临时改法:select @@GLOBAL.sql_mode;查询当前mysql的模式去掉ONLY_FULL_GROUP_BY重新设置:set @@GLOBAL.sql_mode='STRICT_TRA ...