这题好像比较牛逼,好像又不是怎么样。

考虑两个串是如何计算 LCS 的。

这还不简单?\(dp[n][m]=\max(\max(dp[n-1][m],dp[n][m-1]),[s[n]==t[m]]dp[n-1][m-1])\)。

我们发现一件事情:\(dp[n][m]-dp[n][m-1]\leq 1\)。

接下来引入一个叫 DP 套 DP 的神秘玩意儿。

大概其实就是在 DP 的转移 DAG(或者 DFA) 上面搞事情。

我们对 \(t\) 状压,表示当前的 \(s\) 和 \(t\) 的匹配状态。

我们如果知道匹配状态是可以直接还原 dp 数组的。我们直接还原,然后枚举 \(s\) 当前是哪一个字符,然后把转移边丢出来就好了。

以及,这个转移 DAG 包含了所有可能的边。

所有我们需要做的就是枚举当前匹配状态和下一个字符,然后把转移边丢出来。

然后转移就好了。

对于 NOI,只需要额外记录当前匹配到哪个字符,再处理一下即可。

复杂度 \(O(m2^k+k2^k)\)。

#include<cstdio>
typedef unsigned ui;
const ui mod=1e9+7;
ui n,m,lim,t[20],ans[20],ppc[1<<15],trans[1<<15|1][3],f[1<<15|1][3],g[1<<15|1][3];char s[20];
ui dp[2][20];
inline ui max(const ui&a,const ui&b){
return a>b?a:b;
}
inline void Add(ui&a,const ui&b){
if((a+=b)>=mod)a-=mod;
}
inline void init(){
lim=1<<m;
for(ui i=0;i<m;++i)t[i]=s[i]=='N'?0:s[i]=='O'?1:2;
for(ui S=0;S<lim;++S){
for(ui i=0;i<m;++i)dp[0][i]=S>>i&1;
for(ui i=1;i<m;++i)dp[0][i]+=dp[0][i-1];
for(ui s=0;s<3;++s){
dp[1][0]=dp[0][0];
if(s==t[0])dp[1][0]=1;
for(ui i=1;i<m;++i){
dp[1][i]=max(dp[1][i-1],dp[0][i]);
if(s==t[i])dp[1][i]=max(dp[1][i],dp[0][i-1]+1);
}
for(ui i=1;i<m;++i)trans[S][s]|=dp[1][i]-dp[1][i-1]<<i;trans[S][s]|=dp[1][0];
}
}
}
signed main(){
scanf("%u%u%s",&n,&m,s);init();f[0][0]=1;
for(ui i=0;i<n;++i){
for(ui S=0;S<lim;++S){
if(f[S][0]){
Add(g[trans[S][0]][1],f[S][0]);
Add(g[trans[S][1]][0],f[S][0]);
Add(g[trans[S][2]][0],f[S][0]);
}
if(f[S][1]){
Add(g[trans[S][0]][1],f[S][1]);
Add(g[trans[S][1]][2],f[S][1]);
Add(g[trans[S][2]][0],f[S][1]);
}
if(f[S][2]){
Add(g[trans[S][0]][1],f[S][2]);
Add(g[trans[S][1]][0],f[S][2]);
}
}
for(ui S=0;S<lim;++S){
f[S][0]=g[S][0];f[S][1]=g[S][1];f[S][2]=g[S][2];
g[S][0]=g[S][1]=g[S][2]=0;
}
}
for(ui S=0;S<lim;++S){
ppc[S]=ppc[S>>1]+(S&1);
for(ui i=0;i<3;++i)Add(ans[ppc[S]],f[S][i]);
}
for(ui i=0;i<=m;++i)printf("%u\n",ans[i]);
}

LGP4590题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. C语言非阻塞式键盘监听

    监听键盘可以使用C语言的字符输入函数,例如 getchar.getch.getche 等,使用getche函数监听键盘的例子: #include <stdio.h> #include &l ...

  2. NSSet和NSMutableSet - By吴帮雷

    1.NSSet的使用 [NSSet setWithSet:(NSSet *)set]; 用另外一个set对象构造 [NSSet setWithArray:(NSArray *)array];用数组构造 ...

  3. PL/SQL批量执行SQL脚本文件

    1.选择File > New > Command Windows(命令窗口) 2.输入 @ 符号,之后敲击回车键.从本地选择执行的 SQL脚本 等待批量命令全部执行成功,关闭页面即可 新增 ...

  4. 根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用

    目录 步骤一.下载省市区边界数据 步骤二.解析CSV文件导入数据库 步骤三.在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机定位 ...

  5. 6、前端--DOM操作(查找标签、节点操作、获取值操作、class操作、样式操作、绑定事件、内置参数this)

    DOM操作之查找标签 前缀关键字>>>:document # 基本查找(核心) document.getElementById 根据ID获取一个标签 document.getElem ...

  6. k8s集群中部署prometheus server

    1.概述 本文档主要介绍如何在k8s集群中部署prometheus server用来作为监控的数据采集服务器,这样做可以很方便的对k8s集群中的指标.pod的.节点的指标进行采集和监控. 2.下载镜像 ...

  7. 通过修改注册表将右alt键映射为application键

    通过修改注册表将右alt键映射为application键的方法有许多键盘没有APPLICATION(上下文菜单)键,本文将教您如何把右ALT键映射为apps键.1.映射请将以下注册表信息用记事本保存为 ...

  8. [LeetCode]1.Two Sum 两数之和(Java)

    原题地址:two-sum 题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标. 你可以假设每 ...

  9. 突然发现,npm里request依赖包已经弃用,怎么办?

    摘要:在npm官网查看了request依赖包的当前状态,果然在2020年就被弃用了. 本文分享自华为云社区<npm里request依赖包已经弃用?致敬并调研替代方案!>,作者: gentl ...

  10. Java基于ClassLoder/ InputStream 配合读取配置文件

    阅读java开源框架源码或者自己开发系统时配置文件是一个不能忽略的,在阅读开源代码的过程中尝尝困惑配置文件是如何被读取到内存中的.配置文件本身只是为系统运行提供参数的支持,个人阅读源码时重点不大可能放 ...