题目传送门

题目大意

给出一个长度为 \(n\) 的字符串,对于每个 \(k\in [0,n]\),求出有多少个长度为 \(m\) 的字符串满足两者最长公共子序列长度为 \(k\)。

\(n\le 15,m\le 10^3\),答案对 \(10^9+7\) 取模。

思路

难得扣shi。。。

首先,我们发现如果对两个已知字符串求最长公共子序列,那么我们可以设 \(f_{i,j}\) 表示第 1 个字符串匹配到 \(i\),第 2 个字符串匹配到 \(j\) 的最长匹配长度。不难得到转移式:

\[f_{i,j}=f_{i-1,j-1}+1\{a_i=b_j\}
\]
\[f_{i,j}=\max\{f_{i-1,j},f_{i,j-1}\}
\]

于是你发现我们一个字符串其实并不需要知道每一位,我们只需要知道 \(f_{i,j}\) 即可。但是你发现你不好把这个压进状态里面,但是你发现对于每一个 \(i\),\(j\) 每变化 \(1\) 位答案最多只会增加 \(1\),于是你可以考虑把每一位的增加量存进状态里面,这样你就可以做到 \(\Theta(2^nm)\)了。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define mod 1000000007
#define MAXM 1005
#define MAXN 15 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} char s[MAXN];
int n,m,ans[MAXN],dp[1 << MAXN][MAXM];
void Add (int &a,int b){a = a + b >= mod ? a + b - mod : a + b;} int a[MAXN],b[MAXN],trans[1 << MAXN][4]; int getid (char c){return c == 'A' ? 0 : (c == 'T' ? 1 : (c == 'C' ? 2 : 3));} void init (){
for (Int S = 0;S < 1 << n;++ S){
for (Int i = 1;i <= n;++ i) a[i] = a[i - 1] + (S >> i - 1 & 1);
for (Int i = 0;i < 4;++ i){
for (Int j = 1;j <= n;++ j)
if (getid (s[j]) == i) b[j] = a[j - 1] + 1;
else b[j] = max (b[j - 1],a[j]);
trans[S][i] = 0;
for (Int j = 1;j <= n;++ j) trans[S][i] |= b[j] - b[j - 1] << j - 1;
}
}
} int popcount (int S){
int res = 0;for (Int i = 0;i < n;++ i) res += S >> i & 1;
return res;
} signed main(){
int t;read (t);
while (t --> 0){
scanf ("%s",s + 1),read (m);
n = strlen (s + 1),init ();
memset (dp,0,sizeof (dp)),dp[0][0] = 1;
for (Int i = 0;i < m;++ i)
for (Int S = 0;S < 1 << n;++ S)
for (Int j = 0;j < 4;++ j)
Add (dp[trans[S][j]][i + 1],dp[S][i]);
for (Int i = 0;i <= n;++ i) ans[i] = 0;
for (Int S = 0;S < 1 << n;++ S) Add (ans[popcount (S)],dp[S][m]);
for (Int i = 0;i <= n;++ i) write (ans[i]),putchar ('\n');
}
return 0;
}

题解 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. 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. BZOJ3864 & HDU4899:Hero meet devil——题解

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

  5. bzoj3864: Hero meet devil

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

  6. 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 ...

  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 3864: Hero meet devil(dp套dp)

    题面 给你一个只由\(AGCT\)组成的字符串\(S (|S| ≤ 15)\),对于每个\(0 ≤ .. ≤ |S|\),问 有多少个只由\(AGCT\)组成的长度为\(m(1 ≤ m ≤ 1000) ...

随机推荐

  1. vue3.0入门(二)

    前言 最近在b站上学习了飞哥的vue教程 学习案例已上传,下载地址 指令 #id2{ // css部分 font-size: 24px; color: green; } v-bind:href=&qu ...

  2. php ltrim() rtrim() trim()删除字符空格

    php$str=" 去除前后空格 ";echo "方括号中为原始字符串:[".$str."]";echo "原始字符串长度:&qu ...

  3. 使用Keepalived实现Nginx的自动重启及双主热备高可用

    1.概述 之前我们使用Keepalived实现了Nginx服务的双机主备高可用,但是有几个问题没有解决,今天一起探讨一下. 1)在双机主备机制中,Keepalived服务如果宕了,会自动启用备机进行服 ...

  4. 羽夏笔记——PE结构(不包含.Net)

    写在前面   本笔记是由本人独自整理出来的,图片来源于网络.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你 ...

  5. shell运算方式

    1.(())--整数运算 [root@m01 /server/scripts]# a=1 [root@m01 /server/scripts]# b=2 [root@m01 /server/scrip ...

  6. 算法:实现strStr(),字符串indexOf方法

    描述 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返回  -1. 个人思路: ...

  7. github上使用C语言实现的线程池

    网上介绍线程池的知识很多,但是在代码实现上介绍的又不是那么多.而且给人的一种感觉就是:你的这种实现是正规的方式还是你自己的实现? 如果有这么个疑问,且想找一个靠谱的代码拿来使用,那么这个项目是个不错的 ...

  8. Element NavMenu动态生成导航菜单

    为了演示方便,不从数据库获取了 {     "data":[         {             "id":125,             " ...

  9. C# Dapper基本三层架构使用 (三、BLL)

    BLL层介绍 业务逻辑层用于做一些有效性验证的工作,以更好的保证程序运行的健壮性.如完成数据添加.修改和查询业务等:不允许指定的文本框中输入空字符串,数据格式是否正确以及数据类型验证:用户权限的合法性 ...

  10. Hash值和位运算

    一.Hash 1.md5是hash算法,不可逆,还原的是暴力穷举的方式解析的:加盐之后穷举也不能还原: 2.压缩映射会有重复,即哈希冲突: 二.ConcurrentHashMap 1.putIfAbs ...