题目

给出一个由AGTC组成的字符串\(S\),长度为\(n\),对于每个\(i\in [0,n]\),问有多少个长度为\(m\),仅含有AGTC的字符串\(T\)使得\(S\)与\(T\)的最长公共子串长度为\(i\)。\((n\le 15,m\le 1000)\)

Sample Input

GTC
10

Sample Output

1
22783
528340
497452

分析

这是一个经典的问题,解法称为dp套dp。这一类问题要求解的是有多少种输入可以使得一个dp的最终结果为一个特定值。在这道题中的表现就是,求有多少个字符串\(T\)使得求解lcs的dp的最终结果为\(i\)。对于这类问题,一般的方法是,对于内部dp(这里的lcs)观察它的求解过程,把dp的过程状态压缩,放在外层dp中。

观察lcs的求解过程:

\[lcs[i][j]=max
\begin{cases}
lcs[i-1][j-1]+1 & \text{if t[i]=s[j]} \\
lcs[i-1][j] \\
lcs[i][j-1]
\end{cases}
\]

注意到这个转移的过程中,一行只和上一行有关,而且同一行中相邻两位最多差1,所以我们可以把一行差分,状态压缩。即令\(f[i][j]\)表示枚举到第\(i\)个字符,这时候内层dp状态为\(j\)的情况数。那么可以直接得到计算方程:

\[\begin{aligned}
f[i][trans(j,k)]+=f[i-1][j]
\end{aligned}
\]

其中\(trans(j,k)\)表示从\(j\)状态加一个字母\(k\)转移到的状态。比如说,\(s=\text{'ACT'},j=010\),由于差分过,所以原来的状态是\(011\),即当前的匹配是C。接下来加入一个T,那么状态会变成\(012\),压缩后变为\(011\)。注意到这个trans是固定的,所以可以每次预处理。

预处理复杂度为\(O(kn2^n)\),外层dp复杂度为\(O(km2^n)\)。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
const int maxn=15;
const int maxm=1<<maxn;
const int maxa=1e3+1;
const int q=1e9+7;
const char sta[]=" ACGT";
char s[maxn+1];
int t[maxm][5],f[maxa+2][maxm+2],ans[maxn+2],n,a[maxn+2];
int change(char c) {
for (int i=1;i<=4;++i) if (c==sta[i]) return i;
return 5;
}
void add(int &x,int y) {
x+=y;
if (x>q) x-=q;
}
int count(int x) {
int ret=0;
for (int i=0;i<maxn;++i) ret+=((x>>i)&1);
return ret;
}
int tf[2][maxn+2];
int trans(int sit,int c) {
memset(tf,0,sizeof tf);
for (int i=0;i<n;++i) tf[0][i+1]=tf[0][i]+((sit>>i)&1);
for (int i=1;i<=n;++i) {
int tmp=0;
if (a[i]==c) tmp=max(tmp,tf[0][i-1]+1);
tmp=max(tmp,max(tf[0][i],tf[1][i-1]));
tf[1][i]=tmp;
}
int ret=0;
for (int i=0;i<n;++i) ret+=(1<<i)*(tf[1][i+1]-tf[1][i]);
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("my.out","w",stdout);
#endif
int T;
scanf("%d",&T);
while (T--) {
memset(ans,0,sizeof ans);
memset(f,0,sizeof f);
memset(a,0,sizeof a);
scanf("%s",s+1);
n=strlen(s+1);
int m;
scanf("%d",&m);
f[0][0]=1;
for (int i=1;i<=n;++i) a[i]=change(s[i]);
for (int j=0;j<(1<<n);++j) for (int k=1;k<=4;++k) t[j][k]=trans(j,k);
for (int i=1;i<=m;++i) {
for (int j=0;j<(1<<n);++j) {
for (int k=1;k<=4;++k) {
int s=t[j][k];
add(f[i][s],f[i-1][j]);
}
}
}
for (int i=0;i<(1<<n);++i) add(ans[count(i)],f[m][i]);
for (int i=0;i<=n;++i) printf("%d\n",ans[i]);
}
return 0;
}

bzoj3864-hdu4899-Hero meet devil的更多相关文章

  1. 【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 ...

  2. HDU4899 Hero meet devil DP套DP

    陈老师的题QwQ 原题链接 题目大意 有两个字符串\(S\)和\(T\)(都只能由'A','C','G','T'这四个字符组成),\(S\)已知\(T\)未知,还知道\(S\)的长度为\(m\).求满 ...

  3. hdu4899 Hero meet devil

    题目链接 题意 给出一个长度字符串\(T\),其中只包含四种字符\((A,C,G,T)\),需要找一个字符串\(S\),使得\(S\)的长度为\(m\),问\(S\)和\(T\)的\(lcs\)为\( ...

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

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

  5. BZOJ3864 & HDU4899:Hero meet devil——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3864 http://acm.hdu.edu.cn/showproblem.php?pid=4899 ...

  6. bzoj3864: Hero meet devil

    Description There is an old country and the king fell in love with a devil. The devil always asks th ...

  7. BZOJ3864: Hero meet devil(dp套dp)

    Time Limit: 8 Sec  Memory Limit: 128 MBSubmit: 397  Solved: 206[Submit][Status][Discuss] Description ...

  8. BZOJ3864: Hero meet devil【dp of dp】

    Description There is an old country and the king fell in love with a devil. The devil always asks th ...

  9. bzoj千题计划241:bzoj3864: Hero meet devil

    http://www.lydsy.com/JudgeOnline/problem.php?id=3864 题意: 给你一个DNA序列,求有多少个长度为m的DNA序列和给定序列的LCS为0,1,2... ...

  10. HDU 4899 Hero meet devil(状压DP)(2014 Multi-University Training Contest 4)

    Problem Description There is an old country and the king fell in love with a devil. The devil always ...

随机推荐

  1. 洛谷P2252 取石子游戏(威佐夫博弈)

    题目背景 无 题目描述 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  2. spring使用set方法注入的常见类型写法

    首先配置spring的pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...

  3. Bootstrap基础篇—常见的CSS类

    一.标题 标签 大小 h1 36px h2 30px h3 24px h4 18px h5 14px h6 12px 二.常见的内联样式 标签 用途 del 删除的文本 s 无用的文本 ins 插入的 ...

  4. Selenium(Python) ddt读取Excel文件数据驱动

    首先, 引入xlrd模块: ExcelDDT.py: import unittestfrom time import sleep from ddt import ddt, datafrom selen ...

  5. 第5章 Linux网络编程基础

    第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...

  6. <cassert>

    文件名:  <cassert> (assert.h) 这是一个C语言的诊断库,assert.h文件中定义了一个可作为标准调试工具的宏函数: assert ; 下面介绍这个宏函数:asser ...

  7. git 跟踪分支 远程跟踪分支 学习笔记

    远程跟踪分支相当于一个只读仓库指针,从服务器上获取数据,不可以被本地直接修改. 跟踪分支相当于一个本地指针   用于项目更新和迭代. 1跟踪分支  (tracking  branch)   逻辑示意图 ...

  8. MySQL三方面优化

    第一方面:30种mysql优化sql语句查询的方法1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用 ...

  9. 【转】Haml 这货是啥? 附参考

    Haml是一种用来描述任何XHTML web document的标记语言,它是干净,简单的.而且也不用内嵌代码.Haml的职能就是替代那些内嵌代码的page page templating syste ...

  10. 剑指offer-二叉树中和为某一值的路径24

    题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大 ...