题目

给出一个由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. 一起来写段JS drag代码

    http://www.cnblogs.com/275095923/archive/2010/12/09/1901352.html

  2. 北京Uber优步司机奖励政策(1月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. SpringBoot-01:什么是SpringBoot?

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- SpringBoot: Spring Boot可以轻松创建独立的,生产级的基于Spring的应用程序,您可以“ ...

  4. Awesome Django

     Awesome Django    If you find Awesome Django useful, please consider donating to help maintain it. ...

  5. android 学习六 构建用户界面和使用控件

    1.常用Android控件最终都会继承自View类 2.ViewGroup是一些布局类列表的基类,包括View和ViewGroup 3.构造界面的三种方法    a.完全使用代码(太灵活,而不好维护) ...

  6. TPO-10 C2 Return a literature book

    TPO-10 C2 Return a literature book 第 1 段 1.Listen to a conversation between a student and an employe ...

  7. VMware SDK使用指南

    刚开始用VMware官方推荐的SDK,真的是又臭又长,代码结构不清晰,易读性差.后来VMware的同学给推荐了一款开源的SDK,一上手感觉工作效率提高了100倍!推荐大家使用~. 该SDK对VMwar ...

  8. CPU设计学习-流水线

    各种名词 标量流水线 超级流水线 超标量流水线与多发射技术 经典五级流水线 IF |Instruction Fetch,取指 ID |Instruction Decode,译码 EX |Execute ...

  9. 第一周 Welcome

    什么是机器学习 您也许一天用它几十次都不知道,每次你用google或者bing搜索网页感觉很厉害,因为他们用机器学习软件来设计网页排名,当你用Facebook或Apple的照片软件而它们知道照片里面哪 ...

  10. day-16 CNN卷积神经网络算法之Max pooling池化操作学习

    利用CNN卷积神经网络进行训练时,进行完卷积运算,还需要接着进行Max pooling池化操作,目的是在尽量不丢失图像特征前期下,对图像进行downsampling. 首先看下max pooling的 ...