Decode Ways

A message containing letters from A-Z is being encoded to numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26

Given an encoded message containing digits, determine the total number of ways to decode it.

For example,
Given encoded message "12",it could be decoded as "AB" (1 2) or "L" (12).

The number of ways decoding "12" is 2.


public class Solution {
    public int numDecodings(String s) {
		// Start typing your Java solution below
		// DO NOT write main() function
		int n = s.length();
		if (n == 0)
			return 0;
		int[] res = new int[n + 1];
		res[0] = 1;
		if (s.charAt(0) != '0')
			res[1] = 1;
		String temp;
		for (int i = 1; i < n; ++i) {
			temp = s.substring(i - 1, i + 1);
			int value = Integer.parseInt(temp);
			if (s.charAt(i) != '0')
				res[i + 1] = res[i];
			if (value > 9 && value < 27) {
				res[i + 1] += res[i - 1];
			}
		}
		return res[n];
	}
}


### ### P3494 [POI2009] KOD-The Code 题目解析及解法 P3494 [POI2009] KOD-The Code 是一道来自波兰信息学奥林匹克竞赛的编程题,题目要求对给定的字符串进行解码,并找出其中是否存在多个可能的解码方式,从而判断是否会产生歧义。 #### 题意理解 题目给出一个由数字组成的字符串和一个编码规则表,其中每个编码对应一个字符。要求判断该数字字符串是否可以唯一解码为对应的字符序列。如果存在多种解码方式,则输出 `NIE`(波兰语“否”),否则输出 `TAK`(波兰语“是”)以及唯一的解码结果。 此问题与经典的动态规划问题“解码方法”(Decode Ways)类似,但增加了对唯一性的判断要求。 #### 解题思路 采用动态规划方法,维护两个状态数组: - `dp[i]` 表示前 `i` 个字符的解码方式总数。 - `path[i]` 表示从前 `i` 个字符的某一种解码路径中最后一个字符的起始位置。 初始状态为 `dp[0] = 1`,表示空字符串有一种解码方式。 遍历字符串从左到右,对于每个位置 `i`,尝试从 `i - len` 到 `i` 的子串是否是一个有效的编码(`len` 为编码长度,通常不超过 2 或 3,视具体题目设定而定)。如果存在这样的编码,则更新 `dp[i] += dp[i - len]`,并记录路径。 最后,如果 `dp[n] == 0`,说明无法解码;如果 `dp[n] > 1`,说明存在多个解码方式;否则输出唯一解码结果。 #### 代码实现(C++) ```cpp #include <bits/stdc++.h> using namespace std; unordered_map<string, char> codeMap; const int MAXN = 1000005; int dp[MAXN]; // dp[i] 表示前i个字符的解码方式数 int last[MAXN]; // last[i] 表示前i个字符中最后一个字符的起始位置 bool multi[MAXN]; // 是否存在多个解码方式 int main() { ios::sync_with_stdio(false); cin.tie(0); int n, m; string s; cin >> n >> m >> s; for (int i = 0; i < m; ++i) { string code; char ch; cin >> code >> ch; codeMap[code] = ch; } dp[0] = 1; for (int i = 1; i <= n; ++i) { for (int len = 1; len <= 3 && i - len >= 0; ++len) { string sub = s.substr(i - len, len); if (codeMap.count(sub)) { dp[i] += dp[i - len]; if (dp[i] > 1) multi[i] = true; if (dp[i - len] > 1) multi[i] = true; last[i] = i - len; } } } if (dp[n] == 0) { cout << "NIE" << endl; return 0; } if (multi[n]) { cout << "NIE" << endl; return 0; } cout << "TAK" << endl; string res; int pos = n; while (pos > 0) { string sub = s.substr(last[pos], pos - last[pos]); res.push_back(codeMap[sub]); pos = last[pos]; } reverse(res.begin(), res.end()); cout << res << endl; return 0; } ``` #### 时间复杂度分析 - 时间复杂度:`O(n * k)`,其中 `k` 是编码的最大长度(通常为 3)。 - 空间复杂度:`O(n)`,用于存储动态规划数组和路径信息。 该算法在实际竞赛中表现良好,能够处理最大输入规模。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值