从递归到动态规划-解码方法Ⅱ
解码方法Ⅱ
Solution
与上一个解码方法的区别就在于分的情况更多更细了,要仔细考虑每一种情况,在递归和dp的思路上面没有什么太大的变化。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
const int mod = 1e9 + 7;//普通递归
int f1(string s, int i) {int n = s.length();if (i >= n) return 1;int ans = 0;if (s[i] == '0') ans = 0;else {if (s[i] != '*') {ans += f1(s, i + 1) % mod;ans %= mod;if (i + 1 < n && s[i + 1] != '*' && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) {ans += f1(s, i + 2) % mod;ans %= mod;}else if (i + 1 < n && s[i + 1] == '*') {if (s[i] == '1') { ans += 9 * f1(s, i + 2) % mod; ans %= mod; }if (s[i] == '2') { ans += 6 * f1(s, i + 2) % mod; ans %= mod; }}}else {ans += 9 * f1(s, i + 1) % mod;ans %= mod;if (i + 1 < n && s[i + 1] != '*') {if (s[i + 1] - '0' <= 6) { ans += 2 * f1(s, i + 2) % mod; ans %= mod; }else { ans += f1(s, i + 2) % mod; ans %= mod; }}else if (i + 1 < n && s[i + 1] == '*') {ans += 15 * f1(s, i + 2) % mod;ans %= mod;}}}return ans;
}//带缓存表的递归
long long f2(string s, int i, vector<long long>& dp) {int n = s.length();if (i >= n) return 1;if (dp[i] != -1) return dp[i];long long ans = 0;if (s[i] == '0') ans = 0;else {if (s[i] != '*') {ans += f2(s, i + 1, dp) % mod;ans %= mod;if (i + 1 < n && s[i + 1] != '*' && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) {ans += f2(s, i + 2, dp) % mod;ans %= mod;}else if (i + 1 < n && s[i + 1] == '*') {if (s[i] == '1') { ans += 9 * (f2(s, i + 2, dp) % mod); ans %= mod; }if (s[i] == '2') { ans += 6 * (f2(s, i + 2, dp) % mod); ans %= mod; }}}else {ans += 9 * (f2(s, i + 1, dp) % mod);ans %= mod;if (i + 1 < n && s[i + 1] != '*') {if (s[i + 1] - '0' <= 6) { ans += 2 * (f2(s, i + 2, dp) % mod); ans %= mod; }else { ans += f2(s, i + 2, dp) % mod; ans %= mod; }}else if (i + 1 < n && s[i + 1] == '*') {ans += 15 * (f2(s, i + 2, dp) % mod);ans %= mod;}}}dp[i] = ans;return ans;
}//动态规划
int f3(string s) {int n = s.length();vector<long long>dp(n + 1, 0);dp[n] = 1;for (int i = n - 1; i >= 0; --i) {long long ans = 0;if (s[i] == '0') ans = 0;else {if (s[i] != '*') {ans += dp[i + 1] % mod;ans %= mod;if (i + 1 < n && s[i + 1] != '*' && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) {ans += dp[i + 2] % mod;ans %= mod;}else if (i + 1 < n && s[i + 1] == '*') {if (s[i] == '1') { ans += 9 * (dp[i + 2] % mod); ans %= mod; }if (s[i] == '2') { ans += 6 * (dp[i + 2] % mod); ans %= mod; }}}else {ans += 9 * (dp[i + 1] % mod);ans %= mod;if (i + 1 < n && s[i + 1] != '*') {if (s[i + 1] - '0' <= 6) { ans += 2 * (dp[i + 2] % mod); ans %= mod; }else { ans += dp[i + 2] % mod; ans %= mod; }}else if (i + 1 < n && s[i + 1] == '*') {ans += 15 * (dp[i + 2] % mod);ans %= mod;}}}dp[i] = ans;}return dp[0];
}int numDecodings1(string s) {return f1(s, 0);
}int numDecodings2(string s) {int n = s.length();vector<long long>dp(n + 2, -1);return f2(s, 0, dp);
}int numDecodings(string s) {return f3(s);
}int main() {return 0;
}