hdu4899 Hero meet devil
题意
给出一个长度字符串\(T\),其中只包含四种字符\((A,C,G,T)\),需要找一个字符串\(S\),使得\(S\)的长度为\(m\),问\(S\)和\(T\)的\(lcs\)为\(0,1,2...|T|\)时,分别有多少种情况。
\(|T| <= 15,m <= 1000\)
思路
考虑\(dp\)套\(dp\)(dp还能嵌套?)
先考虑已知S的情况下如何求\(lcs\)
用\(dp[i][j]\)表示\(S\)到了\(i\)位置,\(T\)到了\(j\)位置,最长公共子序列的长度。
那就有$$dp[i][j] = max(dp[i-1][j],dp[i][j-1]) \
if(S[i] == T[j]) \
dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1)$$
设计状态
用\(f[i][t_0][t_1][t_2]...[t_n]\)来表示\(S\)到了\(i\)位置,\(dp[i][0],dp[i][1],dp[i][2]...dp[i][n]\)分别为\(t_0,t_1,t_2,t_n\)的方案数。
然后发现时间和空间都会炸。所以考虑状压
根据求\(lcs\)的式子可以看出,\(dp[i][j]\)最多只会比\(dp[i][j-1]\)大\(1\),所以只要把f数组后面的数字差分一下,就变成了可以状压的状态。然后只要前缀和一下就可以还原这个数组。
所以用\(f[i][j]\)来表示\(S\)到了第\(i\)个位置,\(dp\)数组是\(j\)这个状态的方案数。
转移
先预处理出一个\(g\)数组,\(g[i][k]\)表示由\(i\)这个状态,下个位置是\(k\)这个字母,会转移成的状态。
这个预处理其实不难。只要先把i这个状态还原回来。然后用求\(lcs\)那个方法\(dp\)一下。最后再转化回去就可以了。
然后就是\(f\)数组的转移了,只要求出来了\(g\)数组,那么\(f\)数组就比较好处理了。
\]
复杂度是\(O(m2^{|T|})\)
代码
/*
* @Author: wxyww
* @Date: 2019-01-20 10:33:34
* @Last Modified time: 2019-01-20 11:40:43
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<ctime>
#include<bitset>
using namespace std;
typedef long long ll;
const int N = 1<<15,mod = 1e9 + 7;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
char s[20];
int f[1005][N];
int n,tot,ss[20],tmp[2][20],sta[N][4];
void pre(int x) {
for(int i = 1;i <= n;++i) {
tmp[0][i] = (x >> (n - i) & 1) + tmp[0][i - 1];
}
for(int k = 0;k <= 3;++k) {
memset(tmp[1],0,sizeof(tmp[1]));
for(int i = 1;i <= n;++i) {
tmp[1][i] = max(tmp[0][i],tmp[1][i - 1]);
if(ss[i] == k)
tmp[1][i] = max(tmp[1][i],tmp[0][i - 1] + 1);
}
int z = 0;
for(int i = 1;i <= n;++i)
z = z << 1 | (tmp[1][i] - tmp[1][i - 1]);
sta[x][k] = z;
}
}
int ans[N];
int calc(int x){
int re = 0;
while(x) {
re += x & 1;
x >>= 1;
}
return re;
}
int main() {
int T = read();
while(T--) {
memset(f,0,sizeof(f));
scanf("%s",s + 1);
n = strlen(s + 1);
int m = read();
for(int i = 1;i <= n;++i) {
if(s[i] == 'A') ss[i] = 0;
else if(s[i] == 'C') ss[i] = 1;
else if(s[i] == 'G') ss[i] = 2;
else ss[i] = 3;
}
tot = (1 << n) - 1;
f[0][0] = 1;
for(int i = 0;i <= tot;++i) pre(i);
for(int i = 1;i <= m;++i)
for(int j = 0;j <= tot;++j)
for(int k = 0;k < 4;++k)
f[i][sta[j][k]] += f[i - 1][j],f[i][sta[j][k]] %= mod;
memset(ans,0,sizeof(ans));
for(int i = 0;i <= tot;++i) {
int z = calc(i);
ans[z] += f[m][i],ans[z] %= mod;
}
for(int i = 0;i <= n;++i) {
printf("%d\n",ans[i]);
}
}
return 0;
}
/*
2
GTC
10
GTC
10
*/
hdu4899 Hero meet devil的更多相关文章
- HDU4899 Hero meet devil DP套DP
陈老师的题QwQ 原题链接 题目大意 有两个字符串\(S\)和\(T\)(都只能由'A','C','G','T'这四个字符组成),\(S\)已知\(T\)未知,还知道\(S\)的长度为\(m\).求满 ...
- bzoj 3864: Hero meet devil [dp套dp]
3864: Hero meet devil 题意: 给你一个只由AGCT组成的字符串S (|S| ≤ 15),对于每个0 ≤ .. ≤ |S|,问 有多少个只由AGCT组成的长度为m(1 ≤ m ≤ ...
- 【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 ...
- BZOJ3864 & HDU4899:Hero meet devil——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3864 http://acm.hdu.edu.cn/showproblem.php?pid=4899 ...
- 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 ...
- bzoj3864: Hero meet devil
Description There is an old country and the king fell in love with a devil. The devil always asks th ...
- BZOJ3864: Hero meet devil(dp套dp)
Time Limit: 8 Sec Memory Limit: 128 MBSubmit: 397 Solved: 206[Submit][Status][Discuss] Description ...
- 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 ...
- DP套DP HDOJ 4899 Hero meet devil(国王的子民的DNA)
题目链接 题意: 给n长度的S串,对于0<=i<=|S|,有多少个长度为m的T串,使得LCS(S,T) = i. 思路: 理解的不是很透彻,先占个坑. #include <bits/ ...
随机推荐
- MySQL中KEY、PRIMARY KEY、UNIQUE KEY、INDEX 的区别
参考:MySQL中KEY.PRIMARY KEY.UNIQUE KEY.INDEX 的区别 对于题目中提出的问题,可以拆分来一步步解决.在 MySQL 中 KEY 和 INDEX 是同义.那这个问题就 ...
- 老男孩python学习自修第二十三天【多线程】
1. 线程的创建与运行 #!/usr/bin/env python # _*_ coding:UTF-8 _*_ from threading import Thread def foo(param1 ...
- Jenkins+PowerShell持续集成环境搭建(三)Web项目
1. 新建一个名字为HelloWorld.Web的Freesyle项目: 2. 配置源码管理: 3. 编译配置: 版本:选择MSBuild4 文件:D:\CI\Config\HelloWorld.We ...
- 4.namespace
命名空间( namespace)是 Linux 内核的一个强大特性,为容器虚拟化的实现带来极大便 利. 利用这一特性,每个容器都可以拥有自己单独的命名空间,运行在其中的应用都像是在 独立的操作系统环境 ...
- xx.hbm.xml中相关重要的配置
1.<!-- 指定hibernate操作数据库时的隔离级别 #hibernate.connection.isolation 1|2|4|8 ...
- HDU3480-Division-斜率dp
首先想到的就是sort一下,然后每个集合都在排过序的数组里面取,不重复. 这样就推出公式dp[i][j] = min(dp[k][j-1] + (s[i]-s[k+1])^2) 其中dp[i][j]为 ...
- Python中xlrd模块解析
xlrd 导入模块 import xlrd 2.打开指定的excel文件,返回一个data对象 data = xlrd.open_workbook(file) ...
- 洛谷3823 [NOI2017] 蚯蚓排队 【哈希】
题目分析: 从$\sum|S|$入手.共考虑$\sum|S|$个$f(t)$.所以我们要一个对于每个$f(t)$在$O(1)$求解的算法.不难想到是哈希. 然后考虑分裂和合并操作.一次合并操作要考虑合 ...
- MYSQL理论
1.数据库相关概念 数据库服务器(本质就是一个台计算机,该计算机之上安装有数据库管理软件的服务端) 数据库管理管理系统RDBMS(本质就是一个C/S架构的套接字软件) 库(文件夹)=====>数 ...
- 洛谷P3381 最小费用最大流
费用流板子 还是一道板子题..先练练手 #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset( ...