你写下了若干 正整数 ,并将它们连接成了一个字符串 num 。但是你忘记给这些数字之间加逗号了。你只记得这一列数字是 非递减 的且 没有 任何数字有前导 0 。
请你返回有多少种可能的 正整数数组 可以得到字符串 num 。由于答案可能很大,将结果对 109 + 7 取余 后返回。
示例 1:
输入:num = "327"
输出:2
解释:以下为可能的方案:
3, 27
327
示例 2:
输入:num = "094"
输出:0
解释:不能有数字有前导 0 ,且所有数字均为正数。
示例 3:
输入:num = "0"
输出:0
解释:不能有数字有前导 0 ,且所有数字均为正数。
示例 4:
输入:num = "9999999999999"
输出:101
提示:
1 <= num.length <= 3500
num 只含有数字 '0' 到 '9' 。
思路:考虑采用动态规划。我们定义dp[i][j]表示前i个字符,并且最后一个数位数小于等于j的方案数。则dp[i][j]=sum(dp[i-len][len]),其中len<=j
class Solution {
private static final int mod = 1000000007;
public int numberOfCombinations(String num) {
int n = num.length();
if (num.charAt(0) == '0')
return 0;
if (n == 1) return 1;
long[][] dp = new long[n][n + 1];
for (int i = 0; i < n; i++) {
dp[i][i + 1] = 1;
if (i > 0)
dp[0][i + 1] = dp[0][i];
}
for (int i = 1; i < n; i++) {
if (num.charAt(i) >= num.charAt(i - 1))
dp[i][1] = dp[i - 1][1];
for (int len = 2; len < i + 1; len++) {
if (num.charAt(i - len + 1) == '0')
continue;
if (i - 2 * len + 1 >= 0 && num.substring(i - 2 * len + 1, i - len + 1).
compareTo(num.substring(i - len + 1, i + 1)) <= 0) {
dp[i][len] = (dp[i][len] + dp[i - len][len]) % mod;
} else
dp[i][len] = (dp[i][len] + dp[i - len][len - 1]) % mod;
}
for (int len = 2; len <= n; len++)
dp[i][len] = (dp[i][len] + dp[i][len - 1]) % mod;
}
for (int i = 0; i <= n; i++)
System.out.println(dp[n - 1][i]);
return (int) dp[n - 1][n];
}
}