题面

给你一个只由\(AGCT\)组成的字符串\(S (|S| ≤ 15)\),对于每个\(0 ≤ .. ≤ |S|\),问

有多少个只由\(AGCT\)组成的长度为\(m(1 ≤ m ≤ 1000)\)的字符串\(T\),使得\(LCS(T,S)=i\)?

题解

老早就听说这个叫做\(dp\ of\ dp\)的神仙了……然而一直没学……

我们先考虑\(LCS\)是怎么转移的,设\(LCS(i,j)\)表示第一个串到\(i\),第二个串到\(j\)为止的最长公共子序列,那么转移为

\[LCS(i,j)=\max
\begin{cases}
LCS(i-1,j-1)+1 &S[i]=T[j]\\
LCS(i,j-1)\\
LCS(i-1,j)
\end{cases}
\]

然后我们发现\(LCS(i,j)\)的值和\(LCS(i,j-1)\)的值相差最多不会超过\(1\)

那么我们把数组的第二维差分一下,再状压成一个二进制序列,然后我们就可以预处理出\(to[s][k]\)表示当前\(LCS\)状态为\(s\),加的下一个字符为\(k\),可以到达的\(LCS\)状态是什么

然后设\(f[i][s]\)表示当前在第\(i\)个位置,此时\(LCS\)状态为\(s\)的方案数

那么转移方程就是

\[f[i][to[s][k]]+=f[i-1][s](k=A,T,G,C)
\]

边界为\(f[0][0]=1\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
const char T[15]={"ATGC"};const int N=(1<<15)+5,P=1e9+7;
inline void Add(R int &x,R int y){(x+=y)>=P?x-=P:0;}
char S[19];int to[N][4],sz[N],f[2][N],ans[1005];
int n,m,lim,t;
void init(){
static int d[19],g[19];
fp(s,0,lim-1){
sz[s]=sz[s>>1]+(s&1);
fp(j,0,n-1)d[j+1]=d[j]+(s>>j&1);
fp(k,0,3){
fp(j,1,n){
g[j]=max(g[j-1],d[j]);
T[k]==S[j]?cmax(g[j],d[j-1]+1):0;
}
to[s][k]=0;
fp(j,0,n-1)g[j+1]-g[j]?(to[s][k]|=(1<<j)):0;
}
}
}
int main(){
// freopen("testdata.in","r",stdin);
int cas;scanf("%d",&cas);
while(cas--){
scanf("%s%d",S+1,&m),n=strlen(S+1),lim=(1<<n);
init(),memset(ans,0,4*(n+1)),memset(f,0,sizeof(f));
f[0][0]=1,t=0;
for(R int i=1;i<=m;++i,t^=1){
memset(f[t^1],0,4*lim);
fp(s,0,lim-1)fp(k,0,3)Add(f[t^1][to[s][k]],f[t][s]);
}
fp(s,0,lim-1)Add(ans[sz[s]],f[t][s]);
fp(i,0,n)printf("%d\n",ans[i]);
}
return 0;
}

bzoj 3864: Hero meet devil(dp套dp)的更多相关文章

  1. BZOJ 3864 Hero meet devil (状压DP)

    最近写状压写的有点多,什么LIS,LCSLIS,LCSLIS,LCS全都用状压写了-这道题就是一道状压LCSLCSLCS 题意 给出一个长度为n(n<=15)n(n<=15)n(n< ...

  2. bzoj 3864: Hero meet devil [dp套dp]

    3864: Hero meet devil 题意: 给你一个只由AGCT组成的字符串S (|S| ≤ 15),对于每个0 ≤ .. ≤ |S|,问 有多少个只由AGCT组成的长度为m(1 ≤ m ≤ ...

  3. BZOJ 3864 Hero meet devil 超详细超好懂题解

    题目链接 BZOJ 3864 题意简述 设字符集为ATCG,给出一个长为\(n(n \le 15)\)的字符串\(A\),问有多少长度为\(m(m \le 1000)\)的字符串\(B\)与\(A\) ...

  4. bzoj 3864: Hero meet devil

    bzoj3864次元联通们 第一次写dp of dp (:з」∠) 不能再颓废啦 考虑最长匹配序列匹配书转移 由于dp[i][j]的转移可由上一行dp[i-1][j-1],dp[i-1][j],dp[ ...

  5. BZOJ 3864 Hero Meets Devil

    题目大意 给定一个由AGCT组成的串\(t\), 求对于所有的\(L \in [1, |t|]\), 有多少个由AGCT组成的串\(s\)满足\(LCS(s, t) = L\). Solution 传 ...

  6. HDU 4899 Hero meet devil (状压DP, DP预处理)

    题意:给你一个基因序列s(只有A,T,C,G四个字符,假设长度为n),问长度为m的基因序列s1中与给定的基因序列LCS是0,1......n的有多少个? 思路:最直接的方法是暴力枚举长度为m的串,然后 ...

  7. 【BZOJ3864】Hero meet devil DP套DP

    [BZOJ3864]Hero meet devil Description There is an old country and the king fell in love with a devil ...

  8. DP套DP

    DP套DP,就是将内层DP的结果作为外层DP的状态进行DP的方法. [BZOJ3864]Hero meet devil 对做LCS的DP数组差分后状压,预处理出转移数组,然后直接转移即可. tr[S] ...

  9. [模板] dp套dp && bzoj5336: [TJOI2018]party

    Description Problem 5336. -- [TJOI2018]party Solution 神奇的dp套dp... 考虑lcs的转移方程: \[ lcs[i][j]=\begin{ca ...

随机推荐

  1. python's thirty day for me 异常处理

    ---恢复内容开始--- 程序的异常:报错之后程序终止. 异常处理搭配使用: l = ['创建老师','创建学校'] while True: try: for num,item in enumerat ...

  2. 解决webpack环境变量NODE_ENV跨平台兼容性问题

    为什么要用cross-env插件 学过webpack的人都知道,webpack可以使用NODE_ENV=development或者NODE_ENV=production这样的方式来设置全局变量 这样的 ...

  3. day6心得

    面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思 ...

  4. leetcode690

    class Solution { public: int getImportance(vector<Employee*> employees, int id) { ; map<int ...

  5. AMFObject 数据格式浅析

    amf.h中关于 AMFObject 是这样的定义的: typedef struct AMFObject { int o_num; struct AMFObjectProperty *o_props; ...

  6. springboot整合redis单机及集群

    一.单机配置 properties配置 #单机redis spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.passwor ...

  7. Hadoop Serialization(third edition)hadoop序列化详解(最新版) (1)

    初学java的人肯定对java序列化记忆犹新.最开始很多人并不会一下子理解序列化的意义所在.这样子是因为很多人还是对java最底层的特性不是特别理解,当你经验丰富,对java理解更加深刻之后,你就会发 ...

  8. cuteFTP软件往linux中上传文件时报…

    我是在win7和VM中的ubuntu传输文件: 使用一个客户端,可以正常的连接,但是当上传文件时,总是报553 Could not create file错误信息. 主要原因是新建的文件夹没有更改权限 ...

  9. easylogging++学习记录(二):流式日志

    easylogging++日志库流式日志的写入,依赖于el::base::Writer类的析构,以debug日志为例:具体代码如下: #define LOG(LEVEL) CLOG(LEVEL, EL ...

  10. SESSION的知识

    android模拟表单用到了httpclient,但是需要了解Jsessionid的相关知识 如下是从一篇博文摘抄来的 在web应用的开发中我们会经常看到这样的url:http://www.xxx.c ...