最近写状压写的有点多,什么LIS,LCSLIS,LCSLIS,LCS全都用状压写了…这道题就是一道状压LCSLCSLCS


题意

给出一个长度为n(n&lt;=15)n(n&lt;=15)n(n<=15)的字符串sss,只由A,T,G,CA,T,G,CA,T,G,C组成。对于0...n0...n0...n的每一个iii,求长度为m(m&lt;=1000)m(m&lt;=1000)m(m<=1000)且只由A,T,G,CA,T,G,CA,T,G,C组成的串中,有多少字符串与sss的最长公共子序列(LCS)(LCS)(LCS)长度为iii。

分析
  • 先想想LCSLCSLCS的转移怎么写的,设lcs(i,j)lcs(i,j)lcs(i,j)表示长度为m(m&lt;=1000)m(m&lt;=1000)m(m<=1000)的未知串匹配到iii,长度为n(n&lt;=15)n(n&lt;=15)n(n<=15)的sss串匹配到jjj的最长公共子序列长度

    lcs(i,j)={lcs(i−1,j−1)+1M[i]=s[j]Max(lcs(i−1,j),lcs(i,j−1))M[i]≠s[j]\large lcs(i,j)=\left\{
    \begin{aligned}
    &amp;lcs(i-1,j-1)+1&amp;M[i]=s[j]\\
    &amp;Max(lcs(i-1,j),lcs(i,j-1))&amp;M[i]≠s[j]\\
    \end{aligned}
    \right.lcs(i,j)=⎩⎨⎧​​lcs(i−1,j−1)+1Max(lcs(i−1,j),lcs(i,j−1))​M[i]=s[j]M[i]̸​=s[j]​可以观察到lcs(i,j)lcs(i,j)lcs(i,j)与lcs(i,j−1)lcs(i,j-1)lcs(i,j−1)的差最多为111,那么我们将lcs(i,0...n−1)lcs(i,0...n-1)lcs(i,0...n−1)的差分数组(01串01串01串)状压,做mmm次转移来统计方案。差分数组的111的个数就是当前状态的LCSLCSLCS的长度。
  • 可以预处理出每个状态后面加一个字符会得到的下一个状态。具体做法可以把差分数组还原成lcslcslcs数组再像普通的LCSLCSLCS来DP,最后再还原。也可以像我这样直接写
    for(int state = 0; state < (1<<n); ++state) //当前状态
    for(int i = 0; i < 4; ++i) { //选哪一个字符
    int res = 0, now = 0, pre = 0; //res存答案
    for(int j = 0; j < n; ++j) {
    int npre = pre + ((state>>j)&1);
    int nnow = max(now, npre);
    if(i == arr[j]) nnow = pre + 1;
    if(nnow > now) res += 1<<j; //大于 说明此处差分数组值为1
    pre = npre, now = nnow;
    }
    //pre:dp[i-1][j-1] npre:dp[i-1][j]
    //now:dp[i][j-1] nnow:dp[i][j]
    to[state][i] = res;
    }
  • 注意清零啥的.
AC CODE
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 15;
const int MAXS = 32768;
const int mod = 1e9 + 7;
inline int num(char c) {
return c == 'A' ? 0 : c == 'T' ? 1 : c == 'G' ? 2 : 3;
}
char s[MAXN];
int n, m, arr[MAXN], ans[MAXN+1], to[MAXS][4], f[2][MAXS], sz[MAXS];
inline void solve() {
scanf("%s%d", s, &m); n = strlen(s);
for(int i = 0; i < n; ++i) arr[i] = num(s[i]);
for(int state = 0; state < (1<<n); ++state)
for(int i = 0; i < 4; ++i) {
int res = 0, now = 0, pre = 0;
for(int j = 0; j < n; ++j) {
int npre = pre + ((state>>j)&1);
int nnow = max(now, npre);
if(i == arr[j]) nnow = pre + 1;
if(nnow > now) res += 1<<j;
pre = npre, now = nnow;
}
//pre:dp[i-1][j-1] npre:dp[i-1][j]
//now:dp[i][j-1] nnow:dp[i][j]
to[state][i] = res;
}
int now = 0; f[now][0] = 1;
while(m--) { now ^= 1;
for(int state = 0; state < (1<<n); ++state) {
for(int i = 0; i < 4; ++i)
f[now][to[state][i]] = (f[now][to[state][i]] + f[now^1][state]) % mod;
f[now^1][state] = 0;
}
}
memset(ans, 0, sizeof ans);
for(int state = 0; state < (1<<n); ++state)
ans[sz[state]] = (ans[sz[state]] + f[now][state]) % mod, f[now][state] = 0;
for(int i = 0; i <= n; ++i)
printf("%d\n", ans[i]);
} int main () {
int T;
for(int state = 0; state < MAXS; ++state)
sz[state] = sz[state>>1] + (state&1);
scanf("%d", &T);
while(T--) solve();
}

BZOJ 3864 Hero meet devil (状压DP)的更多相关文章

  1. HDU 4899 Hero meet devil (状压DP, DP预处理)

    题意:给你一个基因序列s(只有A,T,C,G四个字符,假设长度为n),问长度为m的基因序列s1中与给定的基因序列LCS是0,1......n的有多少个? 思路:最直接的方法是暴力枚举长度为m的串,然后 ...

  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(dp套dp)

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

  4. BZOJ 3864 Hero meet devil 超详细超好懂题解

    题目链接 BZOJ 3864 题意简述 设字符集为ATCG,给出一个长为\(n(n \le 15)\)的字符串\(A\),问有多少长度为\(m(m \le 1000)\)的字符串\(B\)与\(A\) ...

  5. bzoj 3864: Hero meet devil

    bzoj3864次元联通们 第一次写dp of dp (:з」∠) 不能再颓废啦 考虑最长匹配序列匹配书转移 由于dp[i][j]的转移可由上一行dp[i-1][j-1],dp[i-1][j],dp[ ...

  6. BZOJ.4145.[AMPPZ2014]The Prices(状压DP)

    BZOJ 比较裸的状压DP. 刚开始写麻烦惹... \(f[i][s]\)表示考虑了前\(i\)家商店,所买物品状态为\(s\)的最小花费. 可以写求一遍一定去\(i\)商店的\(f[i]\)(\(f ...

  7. BZOJ.3058.四叶草魔杖(Kruskal 状压DP)

    题目链接 \(2^{16}=65536\),可以想到状压DP.但是又有\(\sum A_i\neq 0\)的问题.. 但是\(2^n\)这么小,完全可以枚举所有子集找到\(\sum A_i=0\)的, ...

  8. bzoj 5299: [Cqoi2018]解锁屏幕 状压dp+二进制

    比较简单的状压 dp,令 $f[S][i]$ 表示已经经过的点集为 $S$,且最后一个访问的位置为 $i$ 的方案数. 然后随便转移一下就可以了,可以用 $lowbit$ 来优化一下枚举. code: ...

  9. BZOJ 4197: [Noi2015]寿司晚宴 状压dp+质因数分解

    挺神的一道题 ~ 由于两个人选的数字不能有互质的情况,所以说对于一个质因子来说,如果 1 选了,则 2 不能选任何整除该质因子的数. 然后,我们发现对于 1 ~ 500 的数字来说,只可能有一个大于 ...

随机推荐

  1. Spring Boot系列教程十四:Spring boot同时支持HTTP和HTTPS

    自签证书 openssl生成服务端证书,不使用CA证书直接生成 -in server.csr -signkey server.key -out server.crt # 5.server证书转换成ke ...

  2. //统计报表-供水量统计主列表分页查询 Element-ui的分页插件

    <!-- //分页 --> <div class="pagination">时间(月) <el-pagination @current-change= ...

  3. 2019杭电多校一 C. Milk (dp)

    大意: $n*m$棋盘, 初始位置$(1,1)$, 横坐标为$\frac{m+1}{2}$时可以向下走, 否则只能左右走, 每走一步花费$1$秒. 有$k$管奶, 第$i$罐位置$(r_i,c_i)$ ...

  4. 怎样获取当前对象的原型对象prototype

    1. 使用 Object.getPrototypeOf(); function Person(name){ this.name = name; } var lilei = new Person(&qu ...

  5. vue中子组件的created、mounted钩子中获取不到props中的值问题

    父子组件通信 这个官网很清楚,也很简单,父组件中使用v-bind绑定传送,子组件使用props接收即可 例如: 父组件中: <template> <div> <head- ...

  6. “org/apache/commons/logging/LogFactory”错误的解决方式

    用spring-framework-4.2.6.RELEASE-dist时,发生了如下的错误: [java] view plain copy Exception in thread "mai ...

  7. Linux Jetbrains Datagrip 图标找不到

    问题 系统版本:Ubuntu 18.04,Datagrip版本:2019.2 从官网下载的 tar.gz 解压之后,找到 datagrip.sh 就可以使用了.但是有个问题,它没有自动创建快捷方式,所 ...

  8. JS有关引用对象的拷贝问题

    JS中有关引用对象的拷贝问题 问题描述:在开发过程中,拷贝一个对象数组给另一个数组的时候,改变新数组中对象的属性值,原数组中的对象属性值也跟着改变了. 例如新定义一个数组arr1,里面有两个对象,然后 ...

  9. moment.js(日期处理类库)的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. iOS有哪些数据类型/基本数据类型?

    简述 本文主要探究使用OC作为iOS开发语言时,我们能使用哪些数据类型. 一切类型始于C. C语言的类型 基本数据类型: 基本数据类型(fundamental data types)也叫原始数据类型( ...