#19306. 破译遗传密码
破译遗传密码
这一次,我们将目光投向高中生物必修二《遗传与进化》中关于 基因表达(Translation) 的核心机制——遗传密码子的破译。
这道题目考察的是字符串处理、模运算(Modulo Arithmetic)以及多路状态扫描的思想。难度定位在 GESP 5级(约等于 CSP-J T2/T3)。
题目:破译遗传密码 (Deciphering the Genetic Code)
【背景知识讲解】
在生物体内,mRNA(信使RNA)携带遗传信息指导蛋白质的合成,这个过程叫做翻译。 mRNA上每 3 个相邻的碱基决定一个氨基酸,这 3 个碱基称为一个密码子(Codon)。
翻译过程有严格的规则:
- 起始密码子:翻译通常从
AUG开始(该密码子编码甲硫氨酸)。 - 终止密码子:翻译在遇到
UAA、UGA或UAG时停止(这三个密码子不编码氨基酸,只代表结束)。 - 读码框(Reading Frame):核糖体在读取序列时,是连续地、不重叠地每 3 个碱基读一次。
例如序列 ...C AUG GCU UCA UAA G...:
- 只要识别到
AUG,核糖体就开始工作,翻译出第一个氨基酸。 - 接着读
GCU(第2个)、UCA(第3个)。 - 遇到
UAA,翻译结束。 - 这条多肽链的长度就是 3 个氨基酸。
但是,mRNA序列是连续的字符,我们不知道核糖体是从第0个字符、第1个字符还是第2个字符开始读的(这被称为3种阅读框)。你的任务是找出其中能翻译出的最长的那条肽链。
【题目描述】
给定一个长度为 的 mRNA 序列 (只包含 'A', 'U', 'C', 'G')。 请你寻找满足以下条件的最长子串:
- 该子串以
AUG开头。 - 该子串以
UAA、UGA或UAG结尾。 - 起始子串和终止子串之间(包括起始,不包括终止)的碱基数量必须是 3 的倍数。
- 在起始和终止之间,不能包含其他的终止密码子(即一旦遇到终止就立刻结束)。
请输出该最长子串所能翻译成的氨基酸数量。
(注:起始的 AUG 算 1 个氨基酸,结尾的终止密码子不算氨基酸)。
如果序列中找不到任何符合要求的片段,输出 0。
【输入格式】
第一行包含一个整数 ,表示 mRNA 序列的长度。 第二行包含一个长度为 的字符串 。
【输出格式】
输出一个整数,表示最长多肽链包含的氨基酸数量。
【样例数据】
输入:
13
CAUGUUUUUUUAG
输出:
3
【样例解释】
我们需要对 mRNA 序列进行三种不同“读码框(Frame)”的扫描,以寻找符合条件的最长多肽链:
1. 尝试读码框 1(从下标 0 开始,每次跳 3 个):
- 下标 0:
CAU(不是起始) - 下标 3:
GUU - 下标 6:
UUU - 下标 9:
UUA - ...
- 结果:未发现起始密码子
AUG,该读码框无解。
2. 尝试读码框 2(从下标 1 开始,每次跳 3 个):
- 下标 1:
AUG发现起始密码子!(开始翻译,当前氨基酸数:1) - 下标 4:
UUU普通密码子(当前氨基酸数:2) - 下标 7:
UUU普通密码子(当前氨基酸数:3) - 下标 10:
UAG发现终止密码子! - 结果:翻译结束。该片段为
AUG-UUU-UUU。 - 长度计算:虽然跨度包含终止子,但题目要求输出氨基酸数量(含起始,不含终止)。
- 计算公式:。
- 该链长度为 3。
3. 尝试读码框 3(从下标 2 开始,每次跳 3 个):
- 下标 2:
UGU(不是起始) - 下标 5:
UUU - 下标 8:
UUA - ...
- 结果:未发现起始密码子
AUG,该读码框无解。
综合结论: 所有可能的翻译结果中,最长的长度为 3。
【补充测试点建议】
为了保证测试数据的完备性,建议在后台数据中包含以下情况(数据生成器代码已覆盖):
- 多条链竞争:序列中有两条合法的链,一条长度2,一条长度5,程序需输出5。
- 嵌套干扰:例如
AUG...AUG...UAA。根据生物学规则(也是最长匹配贪心逻辑),通常一旦遇到起始就开始翻译,直到终止。如果中间遇到AUG,视为普通甲硫氨酸。如果这题逻辑是“寻找最长”,那么我们只需记录最外层的即可(代码逻辑已涵盖)。 - 无解情况:整个序列没有
AUG,或者有AUG但后面直到末尾都没有终止密码子。输出 0。 - 跨越边界:
AUG在 的位置,后面不够 3 个字符,无法形成密码子。
【数据范围】
- 对于 100% 的数据:。
- 字符串仅包含 'A', 'U', 'C', 'G'。
一、 思路提示
-
三种“平行世界”:
- 因为密码子是 3 个一组,所以只有三种读取方式:
- 从下标 开始读。
- 从下标 开始读。
- 从下标 开始读。
- 这就是所谓的模 3 同余。我们可以写一个外层循环
frame = 0 到 2,分别处理这三种情况。
- 因为密码子是 3 个一组,所以只有三种读取方式:
-
状态机的思想:
- 对于每一个阅读框(Frame),我们遍历字符串。
- 我们需要一个变量
start_index来记录“当前是否正在翻译中”。- 初始状态:
start_index = -1(表示还没找到 AUG)。 - 如果你读到了
AUG并且start_index == -1:说明新的肽链开始了,记录start_index = 当前下标。- 思考:如果
start_index != -1(已经开始了)又读到了AUG怎么办?生物学上这只是一个普通的甲硫氨酸,继续翻译即可,不需要更新start_index(因为我们要找最长的,显然起点越早越好)。
- 思考:如果
- 如果你读到了
UAA/UGA/UAG并且start_index != -1:说明肽链结束了。- 计算长度:
(当前下标 - start_index) / 3。 - 更新最大值
max_len。 - 重置状态:
start_index = -1。准备寻找下一条肽链。
- 计算长度:
- 初始状态:
-
时间复杂度:
- 每个字符最多被访问常数次(3 个 Frame,每个 Frame 访问一遍)。
- 总复杂度 。符合 的要求。
二、 预备知识点总结
- 字符串子串提取/比较:能够快速判断
S[i]...S[i+2]是否等于 "AUG"。 - 模运算与步长循环:理解
for(int i = frame; i < N; i += 3)的含义。 - 贪心/状态维护:在一次扫描中,通过维护“最早的起点”来获得“最长的长度”。
三、 启发式教学:草稿纸上的推理过程
教练:“我们拿这个序列来做实验:A A U G C C C A U G U U U U A A。”
下标:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
步骤 1:Frame 0 (从下标0开始,看 0, 3, 6...)
i=0:AAU-> 不是。i=3:GCC-> 不是。- ... 这一轮好像没发现 AUG。pass。
步骤 2:Frame 1 (从下标1开始,看 1, 4, 7...)
i=1:AUG-> 发现起始! 标记start = 1。i=4:CCC-> 继续。i=7:AUG-> 这是中间的氨基酸,不管它,继续(我们要最长的,起点不变)。i=10:UUU-> 继续。i=13:UAA-> 发现终止!- 结算:当前位置 13。起点 1.
- 长度 =
(13 - 1) / 3=12 / 3= 4。 - 这段是:
AUG,CCC,AUG,UUU。长度为 4。 - 重置
start = -1。
步骤 3:Frame 2 (从下标2开始,看 2, 5, 8...)
i=2:UGC-> 不是。- ...
教练:“看,通过分三次扫描,我们绝对不会漏掉任何一种可能性。而且逻辑非常清晰,不会乱。”
四、 读题关键词总结
- “最长” 需要一个变量
max_ans维护全局最大值。 - “3的倍数” / “密码子” 提示我们使用
step = 3的循环,并处理 3 种偏移量。 - “不包含其他终止” 说明这是一个简单的线性扫描,遇到终止必须结算,不能跳过。
这道题目结合了生物学中“阅读框”的概念,非常适合用来练习字符串处理和逻辑思维。希望你喜欢!