通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
标注序列还原计数 · 对应本题的思路、过程和代码
标注平台把一条样本的标签序列压缩成了一个数字串:每个标签的类别编号在 1 到 26 之间,直接按顺序拼接,不加分隔符。现在给出压缩后的数字串,请统计它能还原成多少种不同的标签序列。由于答案可能很大,输出对 1000000007 取模后的结果。无法还原时输出 0。
这类题属于算法机考高频题型中「华为 AI 岗 / 序列 DP」方向的高频题型,通常考察对「华为 AI 岗 / 序列 DP」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
输入一行数字串 s。
输出一行一个整数,表示方案数对 1000000007 取模的结果。
1 <= |s| <= 100000;s 仅由数字 0-9 组成。
示例 1
输入示例
12
输出示例
2
两种还原方式
示例 2
输入示例
226
输出示例
3
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
三种还原方式
时间限制 2000 ms · 内存限制 256 MB
这些是真正决定能不能 AC、但通用题解里常被略过的点。
设 dp[i] 为前 i 个字符能够还原出的标签序列数量。第 i 个字符若为 1..9,可以单独构成一个标签,贡献 dp[i-1];它与前一个字符组成的两位数若在 10..26,可以共同构成一个标签,贡献 dp[i-2]。两部分相加后对 1000000007 取模。转移只依赖前两项,可使用两个变量滚动计算。
任意合法还原的最后一个标签只可能占一位或两位,这两类方案互斥且覆盖全部情况。删除最后一个标签后,剩余前缀分别对应 dp[i-1] 或 dp[i-2],因此转移不会遗漏或重复计数。
只需从左到右扫描一次字符串,时间复杂度为 O(n),滚动状态占 O(1) 空间。
字符 0 不能单独构成标签,只能出现在 10 或 20 中;27 到 99 均不是合法的两位标签。首字符为 0 时答案为 0。每一步都应取模,不能仅在最后处理。
# 序列 DP:每位问「单独成编号(1-9)?与前一位组两位(10-26)?」
# 转移同爬楼梯骨架 dp[i]=dp[i-1]+dp[i-2],条件不满足的支路记 0;全程取模 1e9+7
import sys
MOD = 1_000_000_007
def solve() -> None:
s = sys.stdin.readline().strip()
if not s or s[0] == "0":
print(0)
return
prev2, prev1 = 1, 1
for i in range(1, len(s)):
cur = 0
if s[i] != "0":
cur = prev1
two = int(s[i - 1:i + 1])
if 10 <= two <= 26:
cur = (cur + prev2) % MOD
prev2, prev1 = prev1, cur
print(prev1 % MOD)
if __name__ == "__main__":
solve()