题目

给出一个由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. OI生涯回忆录(二)

    (二)NOIP2016之后到HLOI2017 之后变得有点颓废,因为有的地方难度上来了,碰见不会的题我就会放挺.又或者有时候题水,改完了就不思进取了.到了过年前那几天连着考了几天试,好像是长春那边冬令 ...

  2. BZOJ1066_蜥蜴_KEY

    题目传送门 经过长时间的旅行,很长时间没写过博客了,这次把上次WA的题目过了. 由于每次蜥蜴从石柱上跳下时,石柱的高度会-1,可以看做占了一格的流量. 建图: 1.建超级源和超级汇,设超级源连到每只蜥 ...

  3. Luogu P1802 5倍经验日_KEY

    题目传送门 ·背包 这可以说是一道背包的变形. 首先需要考虑到的是如何将ta转换为一个正常 的背包. 这些数据有一个让我们都十分不爽的地方就是有两个值. 所以我们就设置一个基准值,将失败的经验值当做基 ...

  4. Java:IDEA设置虚拟机运行时参数

    第一步:打开“Run->Edit Configurations”菜单 第二步:选择“VM Options”选项,输入你要设置的VM参数 第三步:点击“OK”.“Apply”后设置完成

  5. spring boot 数据库连接

    server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/jdjk?serverTimezone=Asia/Sha ...

  6. CakePHP2.x 发送邮件

    cake提供了多种发送邮件的方法,并且简单实用.以2.x为例 第一步 创建并添加邮件配置信息 拷贝app\Config\email.php.default 为email.php 打开在EmailCon ...

  7. java 面向对象一

    一 基础部分 1.基本数据类型 Java的八种基本数据类型不支持面向对象的编程机制,不具备“对象”的特性:没有成员变量.方法可以调用.java之所以提供这八种基本数据类型,是为了照顾程序员的传统习惯. ...

  8. 一个体验好的Windows 任务栏缩略图开发心得

    本文来自网易云社区 作者:孙有军 前言: 对于一个追求极致体验的软件来说,利用好系统的每一点优秀的特性,将会大大提高软件的品质. Windows vista以来任务栏缩略图,及Win + TAB的程序 ...

  9. hdu2149Public Sale(巴什博弈)

    Public Sale Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  10. Django模型与创建管理员用户

    默认情况下, 配置使用SQLite: