CodeForces 86C Genetic engineering (AC自动机 上 DP)

博客详细解析了CodeForces 86C问题,该问题涉及遗传工程背景下的DNA序列覆盖。通过AC自动机和动态规划(DP)的方法解决如何确保每个位置都能被给定基因片段覆盖的问题。文章讨论了转移状态、预处理以及避免计算重复的关键点,并给出了代码实现。
摘要由CSDN通过智能技术生成

CodeForces 86C Genetic engineering

原题地址http://codeforces.com/problemset/problem/86/C

题意:
基因是一段有遗传效应DNA片段,我们认为这个片段仅由”A”,”T”,”C”,”G”组成,为了方便,我们只需考虑DNA的一条链。
一条DNA单链长度为n,给出m种基因片段(字符串)的集合,希望使得这条链上的每一个位置都受到可以被集合中的基因片段覆盖。注意有基因片段的序列可以相互重叠,一个位置被覆盖当且仅当它被至少一个集合中的序列包含。
问多少种满足条件的链,对1e9+9取模。

数据范围
1<=n<=1000,1<=m<=10 ,集合中的每个序列长度不超过10。

题解:
(今天的T1)
(我的第一道AC自动机上DP)
dp[n][i][k]表示当前作为DNA链上的第n个点,在AC自动机上的i节点,倒数有长度为k的序列还没有被覆盖。
预处理 val[i]= 点 i 表示的字符串可以覆盖的长度,例如 AGCT,在T对应的点的val值就是4。

那么转移就是:
v点是u点的子节点,此时转移dp[i][u][k],表示当前作为DNA链上的第i个点,在AC自动机上的u节点,倒数有长度为k的序列还没有被覆盖。
若此时 val[v]>=k+1 :
dp[i+1][v][0]+=dp[i][u][k]
(表示到当前点可以覆盖了。)
否则:
dp[i+1][v][j+1]+=dp[i][u][k]
(没覆盖的点又多一个)

能够转移到dp[i+1][v][0],只能转移到dp[i+1][v][0]。否则若遇到后面有个很长的串,两种情况就会都被计算。

我在考试时纠结的点在于,会不会有算重的情况:
eg:
AGCT
AGC
T
实际上,在AC自动机上,AGC的末尾并不会转到T,因为他本身有ch[T],
因此并不会直接从fail树上走到T。
如果每个单词节点都向上面的点连边,显然就会出现上述乱跳的情况。

引用\[1\]中提到了一种树形动态规划的方法来解决CodeForces - 982C问题。在这个问题中,subtree指的是子连通块,而不是子树。为了使cnt_white - cnt_black尽可能大,可以使用两次树形动态规划来求解。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。如果ans\[u\]为正,则减去dp\[v\]就是树链所代表的子树的权值。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] 问题: CodeForces - 982C 树形DP是什么问题?如何解决? 回答: CodeForces - 982C是一个树形动态规划问题。在这个问题中,需要求解子连通块的最大权值和,使得cnt_white - cnt_black尽可能大。解决这个问题的方法是使用两次树形动态规划。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] #### 引用[.reference_title] - *1* *2* [CodeForces - 1324F Maximum White Subtree(树形dp)](https://blog.csdn.net/qq_45458915/article/details/104831678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值