Distinct Subsequences----匹配个串串

题目大意

     给定母串S和待匹配串T,求T能在母串S中匹配多少次(不一定要连续匹配,并且母串中多个相同字母可以依次使用,但均只能使用一次,如S=rabbbit  T=rabbit, 则S中三个连续的b可以依次匹配T中两个bb各一次(),故答案为3。

解题思路

    字符串匹配并且要求结果只为一个数字的时候,很多情况都是使用DP,这题也不例外,建立数组dp[i][j]表示按题目要求当前T串前i个字符匹配S串前j个字符的匹配结果。

建立转移方程:

当T[i] != S[j] 时,显然其值不会改变,因此dp[i][j] = dp[i][j-1];

当T[i] == S[j] 时,此时可以考虑从两个方向转移到当前dp[i][j];

第一个方向:dp[i-1][j-1],将T[0...(i-1)]记为T‘ ,表示在T'尾部增加一个当前字符;

第二个方向:dp[i][j-1],将T[0...(i)]记为T‘' ,表示替换掉T’‘尾部的一个字符(必与当前字符相同);

由于整个过程只用从T的前一步状态转移而来,因此使用一个2*n(n为母串S的长度)的二维数组就能实现dp全过程。

总结

      重点考虑匹配串T,分析其每扩展一个字符后,可由哪些原来的状态转移到新的当前状态来。这道题目想到了就不是很难,主要是多了一些不必要的判断,不过为了保证程序易读且正确,加上这些判断也是值得的,可以后期逐步求精。

代码

class Solution {
public:
    int numDistinct(string S, string T) 
    {
        
        int n = S.length();
        int m = T.length(); 
        if (m > n)return 0;
        int dp[2][11000];   
        bool jud = false;
        memset(dp, 0, sizeof(dp));
        int index = 0;
        for (int i = 0; i < n; i ++){
            if (S[i] == T[0]){
               if (!jud){
                  jud = true;
                  dp[index][i] = 1;
               }
               else dp[index][i] = dp[index][i-1]+1;
            }
            else if (i)  dp[index][i] = dp[index][i-1];
        }
        for (int i = 1; i < m; i ++){
            jud = false;
            index^=1;
            
            for (int j = i; j < n; j ++){
                if (T[i] == S[j]){
                   if (!jud){
                      jud = true;
                      dp[index][j] = dp[index^1][j-1];
                   }
                   else  dp[index][j] = dp[index^1][j-1]+dp[index][j-1];
                } 
                else dp[index][j] = dp[index][j-1];
                
            }    
            for (int j = 0; j < n; j ++)   dp[index^1][j] = 0;
        }    
        return dp[index][n-1];
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值