leetcode 639. Decode Ways II (动态规划)

639. Decode Ways II
题目链接

639. Decode Ways II

题意:

A到Z匹配1到26整数,*匹配1到9的任何数字。给定一个字符串,输出可能有的所有匹配情况。

思路

这题是91. Decode Ways的加强版,我们不妨先考虑简单的情况,比如输入为"112",那么可能有点转化方式为:1 1 2;11 2; 1 12。对于第三个字符2,仅考虑他本身时,可以由1 1, 11 转化而来;当考虑两个字符时(即12时),只能由第一个字符转化而来, 也就是1 12。所以我们不妨记dp[i]表示转化到第i个字符可能有的方法总数,那么有:

  1. 当仅考虑一个字符组合时,若s[i]!='0’时,有dp[i]=dp[i]+dp[i-1] ,即 1 1 0, 11 0是不符合规范的
  2. 当考虑连续两个字符组合时,若s[i-1…i]在10到26之间,那么有dp[i]=dp[i]+dp[i-2]成立

现在我们在考虑有"*"的情况,即s[i]==’*’,

  1. 若只考虑一个字符组合,那么有dp[i]=dp[i]+dp[i-1]*9
  2. 若考虑两个字符组合,可以分成四类情况:这里统一用d表示出现的地方为数字
    4.1 组合为dd,那么只要当dd在10到26之间可以直接转化,dp[i]=dp[i]+dp[i-2]
    4.2 组合为**,那么可能的结果为11,12,…,19,21,…,26,即dp[i]=dp[i]+dp[i-2]*15
    4.3 组合为d*,那么可能出现的情况为:如果d==1,dp[i]=dp[i]+dp[i-2]*9;如果d==2,那么dp[i]=dp[i]+dp[i-2]*6
    4.4 组合为*d,那么可能出现的情况为:如果d在1~6之间,dp[i]=dp[i]+dp[i-2]*2;如果d在7~9之间,dp[i]=dp[i]+dp[i-2]

最后注意开long long,不然乘法爆int

class Solution {
public:
    const int Mod=1e9+7;
    
    int numDecodings(string s) {
        if(!s.size()) return 1;
        
        int n=s.size();
        vector<long> dp(n+1,0);//注意这里直接取 long 类型,不然后面乘法爆int
        dp[0]=1;
        
        if(s[0]>='1' && s[0]<='9' ) dp[1]=1;
        else if(s[0]=='*') dp[1]=9;
        
        for(int i=1;i<n;i++){
            
            string tmp1=s.substr(i,1);
            string tmp2=s.substr(i-1,2);
            
            if(tmp1!="0") {
                if(tmp1!="*") dp[i+1]=(dp[i+1]+dp[i])%Mod;
                else{
                    dp[i+1]=(dp[i+1]+dp[i]*9)%Mod; 
                }
            }
                
            //分四种情况讨论
            char t1=tmp2[0];
            char t2=tmp2[1];
            
            if(isdigit(t1) && isdigit(t2)){//dd
                int num2=stoi(tmp2);
                if(num2>=10 && num2<=26) dp[i+1]=(dp[i+1]+dp[i-1])%Mod;
            }
            else if(!isdigit(t1) && !isdigit(t2)){ //**  9+6=15
                dp[i+1]=(dp[i+1]+dp[i-1]*15%Mod)%Mod;
            }
            else if(isdigit(t1) && !isdigit(t2)){ //d*
                if(t1=='1') dp[i+1]=(dp[i+1]+dp[i-1]*9%Mod)%Mod;
                if(t1=='2') dp[i+1]=(dp[i+1]+dp[i-1]*6%Mod)%Mod;
            }
            else{//*d
                if(t2>='0' && t2<='6') dp[i+1]=(dp[i+1]+dp[i-1]*2%Mod)%Mod;
                else dp[i+1]=(dp[i+1]+dp[i-1])%Mod;
            }
        }
        
        return dp[n];
    }

};
posted @ 2020-09-29 11:23  xzhws  阅读(101)  评论(0编辑  收藏  举报